# Migrate a vBulletin 4 forum to Discourse

**URL:** https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881
**Category:** Sysadmins
**Tags:** how-to
**Created:** [28 december 2016 om 14:59 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881 "2016-12-28T14:59:29Z")
**Posts on this page:** 20
**Page:** 5

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [7 februari 2020 om 18:03 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/88 "2020-02-07T18:03:09Z")

</div>

> [@Hisham](#):
>
> Do these links get converted when imported? if not, what happens to them?

Yes, they get converted. I will email you tomorrow!

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [8 februari 2020 om 08:41 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/89 "2020-02-08T08:41:17Z")

</div>

You have to reach trust level 1 to unlock PMs, and you haven’t spent enough time reading topics here to achieve that yet.

---

<div class="post-metadata">

### Author: ![nory](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nory/32/173397_2.png) [@nory](https://meta.discourse.org/u/nory)
#### Post date: [22 maart 2020 om 21:07 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/90 "2020-03-22T21:07:04Z")

</div>

> [@enigmaty](#):
>
> Docker container

Hi, I’m on Docker container (DigitalOcean) and I’m trying to import mybb (I know this tutorial is for Vbulletin but Gemfile thing is similar). I’m stuck to bundle install:

 ![mybb](https://global.discourse-cdn.com/meta/original/3X/f/6/f6476b3effd4c4bc4bebf15e38e983e88d9b2bd8.jpeg)

---

<div class="post-metadata">

### Author: ![chratec](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chratec/32/175969_2.png) [@chratec](https://meta.discourse.org/u/chratec)
#### Post date: [7 april 2020 om 04:06 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/91 "2020-04-07T04:06:41Z")

</div>

Hello,  
We tried to import vbulletin v3.8 to Discourse. This script work fine, with database 300Mb, around 40k user and 60k post. But at the end of this import process we faced the problem with charset.

- our vBulletin 3.8 encoded with charset: latin1  
----\> when process import script MySQL 5.6 on Discourse docker also config with charset UTF-8,
- The import script force the import process convert data to UTF-8,  
so at the end of import process Discourse forum display data as UTF-8 encode error. It’s look like below picture.

1. before import, vB 3.8

2. after import to Discourse  

We tried:

- Convert charset on vB 3.8 to UTF-8 before run import script
- Tested this vb 3.8 database on new one Mysql server the text display normal no encoded error happen.  
So, could you have any advice in this case ?

Appreciate for any support about this (Also very sorry about my English if you hard to understand)

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [7 april 2020 om 17:41 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/92 "2020-04-07T17:41:15Z")

</div>

Here’s a piece of how I fixed a similar problem:

```ruby
    ### WIN1252 encoding
    win_encoded = ''
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 failed for \n\n#{raw}\n\n"
      win_encoded = ''
    end
    raw = win_encoded

```

---

<div class="post-metadata">

### Author: ![chratec](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chratec/32/175969_2.png) [@chratec](https://meta.discourse.org/u/chratec)
#### Post date: [8 april 2020 om 01:18 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/93 "2020-04-08T01:18:46Z")

</div>

You save my life.  
For the easy way, I tried the convert script on post [Migrate a phpBB3 forum to Discourse - #540 by gerhard](https://meta.discourse.org/t/importing-from-phpbb3/30810/540) , help me fix my database charset problem quickly, and it work like charm now.  
Thank you so much for advise

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [25 mei 2020 om 09:32 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/94 "2020-05-25T09:32:13Z")

</div>

Did anyone migrate using the vbulletin5 importer? I may use it in the future, I’d like to know if it already has been used flawlessly.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [25 mei 2020 om 12:37 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/95 "2020-05-25T12:37:13Z")

</div>

I just did an import of vBulletin5 and added some features (permalinks, some formatting, and maybe some other things I don’t remember). I intend to submit a PR, but it hasn’t happened yet.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [14 augustus 2020 om 12:40 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/96 "2020-08-14T12:40:23Z")

</div>

I have a vb5 database dump that contains attachments in it. Can I import them in Discourse or do I need to have all the attachments as **files**?

> [@steven\_so](#):
>
> I’m not sure about the context of this.
> 
> `Copy the attachments to your Discourse instance (for the path check your VB4 settings).`
> 
> Can anyone please help?

Also confused about this. Where should I copy the attachment files in the discourse folder exactly? 🤔

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [18 augustus 2020 om 20:43 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/97 "2020-08-18T20:43:43Z")

</div>

Hi again,  
From what I understand, attachments from the database will work as they seem to be handled the same way as avatars which are in the database as well.

My import is going well, but I ran an arror at 91% of the imported posts 😩

```plaintext
importing posts...
  1425149 / 1564573 ( 91.1%) [1040 items/min] Traceback (most recent call last):
        14: from script/import_scripts/vbulletin5.rb:726:in `<main>'
        13: from /home/canapin/discourse/script/import_scripts/base.rb:47:in `perform'
        12: from script/import_scripts/vbulletin5.rb:49:in `execute'
        11: from script/import_scripts/vbulletin5.rb:300:in `import_posts'
        10: from /home/canapin/discourse/script/import_scripts/base.rb:862:in `batches'
         9: from /home/canapin/discourse/script/import_scripts/base.rb:862:in `loop'
         8: from /home/canapin/discourse/script/import_scripts/base.rb:863:in `block in batches'
         7: from script/import_scripts/vbulletin5.rb:320:in `block in import_posts'
         6: from /home/canapin/discourse/script/import_scripts/base.rb:508:in `create_posts'
         5: from /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         4: from /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         3: from /home/canapin/discourse/script/import_scripts/base.rb:509:in `block in create_posts'
         2: from script/import_scripts/vbulletin5.rb:321:in `block (2 levels) in import_posts'
         1: from script/import_scripts/vbulletin5.rb:450:in `preprocess_post_raw'
script/import_scripts/vbulletin5.rb:450:in `gsub': invalid byte sequence in UTF-8 (ArgumentError)

```

How can I properly identify the post to see what the content looks like in the vbulletin database?

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [18 augustus 2020 om 21:32 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/98 "2020-08-18T21:32:28Z")

</div>

> [@Canapin](#):
>
> How can I properly identify the post to see what the content looks like in the vbulletin database?

Someone suggested ways to use `rescue` to solve those, so you might go back and find that (I can’t remmber if it was in this topic or another one). You could put a `put` in the `rescue` to print out the `id` and/or the text that caused the problem.

> [@Canapin](#):
>
> `invalid byte sequence in UTF-8`

You have an encoding problem.

I used this in a similar import (I think you’d put it in `preprocess_post_raw`)

```plaintext
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 failed for \n\n#{raw}\n\n"
      win_encoded = ''
    end

```

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [19 augustus 2020 om 07:59 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/100 "2020-08-19T07:59:26Z")

</div>

Hi,  
I modified the the importer and added your script as following:

```plaintext
  def preprocess_post_raw(raw)
    return "" if raw.blank?
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 failed for \n\n#{raw}\n\n"
      win_encoded = ''
    end
    # decode HTML entities
    raw = @htmlentities.decode(raw)

    # fix whitespaces
    raw = raw.gsub(/(\\r)?\\n/, "\n")
      .gsub("\\t", "\t")

```

The invalid byte sequence in UTF-8 happens on this part : `raw = raw.gsub(/(\\r)?\\n/, "\n") .gsub("\\t", "\t")`.

Then I started the importer again. Though it skips already importing data, it took about 6 hours to get to the post that generates an error, and it didn’t add the expected information to see the post content. 😖Any idea why?

edit:

This is probably the post raw content that leads to the error:

```plaintext
I wonder if Billy is enjoying the parade.

Qwertyuiopasdfghjklzxcvbnm&#55356;&#57174;

```

I’ll try to modify the importer script to make it skip (for real) the previous 1.4M posts. WIsh me luck. 🤞

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [19 augustus 2020 om 12:58 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/101 "2020-08-19T12:58:48Z")

</div>

I modified many other importers to include an import\_after setting to allow importing only recent data. You can look at some others to see how I did that.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [19 augustus 2020 om 22:48 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/102 "2020-08-19T22:48:48Z")

</div>

Hi,  
I’ve been able to import almost all my posts! I fixed a few dozens by hand and restarted the import each time it came across a new utf-8 error… 😅

Now, I need to import the attachments (which are stored in the VBulletin database), but it doesn’t work:  
When it starts the process, my ram consumption increases a lot in about 10 or 20 seconds and this error happens:

```plaintext
importing attachments...
Failed to create upload: Cannot allocate memory - grep
Fail

```

My ram:

 ![image](https://global.discourse-cdn.com/meta/original/3X/a/9/a9e432ab2b77cedeecfcf7a1bdd2d3ddc127855f.png)

I use a Discourse development version on a Ubuntu 18 subsystem on Windows 10 and I have 16 GB of RAM.

The attachments take 7 GB from the 13 GB vBulletin database.  
Note that I use the **vbulletin5** importer.

The issue comes from this query:

```SQL
    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid

```

If I do this query in mysql, my remaining ram is filled within seconds.

* * *

(editing my post to remove useless info and questions since I’m figuring out things and providing a workaround)

## Workaround:

I added a limit and a offset to the importer SQL query. I imported the attachments by selecting 20000 of them each time:

```ruby
    uploads = mysql_query <<-SQL
    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid
      LIMIT 20000 OFFSET 0
    SQL

```

I also added an `exit` at the end of the `uploads.each do |upload|` loop to prevent the import script to continue doing things after importing my 20000 uploads.

When my 10000 uploads are imported, I edit the script (thanks `nano +353 ./scripts/import_scripts/vbulletin5.rb` to open the file at the right line) to increase the SQL query `OFFSET` by 10000, and start the importer again… And doing so for my 65000 attachments.

During the attachment imports, I faced several errors and warnings including:

- `W, [2020-08-20T12:05:37.402860 #31042] WARN -- : Bad date/time value "0000:00:00 00:00:00": mon out of range`
- `Post for 490451 not found` (dangling old attachments I guess?)
- some EXIF data error it seems
- `Fail` This one puzzled me and stopped the import script. I checked the first “Fail” I got and the bulletin attachment was sort of broken (no filename), so I commented the `exit` instruction to let the importer continue his importing job when he “fails”, hoping that wouldn’t break anything.

```ruby
       puts "Fail"
       #exit

```

I also had a more annoying error that interrupted the import:

```plaintext
1: from /usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:53:in `save!'
/usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:80:in `raise_validation_error':
Validation failed: Body is limited to 32000 characters; you entered 32323. (ActiveRecord::RecordInvalid)

```

Fortunately, it was a rare error, and I just skipped this attachment until I came across the next identical error. It happened maybe a dozen times on a total of 65000 attachments. I just restarted the import script with a different SQL query offset.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [22 augustus 2020 om 09:38 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/103 "2020-08-22T09:38:04Z")

</div>

Hi,  
I noticed that the custom field **import\_pass** was absent for about 400 users of my remaining 27000 users (I cleaned up 154000 inactive users).

Any idea why?

The forum was migrated from phpBB to vBulletin in May. Could it have something to do with that?

I won’t try to “fix” this thing and import passwords for these 400 users (unless there’s an easy way to do it…?) and that’s not a big issue, so I’m just being curious more than anything else.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [22 augustus 2020 om 18:10 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/104 "2020-08-22T18:10:14Z")

</div>

Hey guys,  
Imported images have the wrong width/height ratio unless I rebake the posts. I’d like to find a way to have the correct ratio (during the import for example) without rebaking.

### More verbose description of the issue:

From what I understand, imported posts aren’t “baked” when Discourse creates the corresponding post (though the **cooked** field is generated somehow), so that’s why importing posts is way faster than baking existing Discourse posts.

My issue is that my imported images have the wrong width/height ratio.

Example of the raw Discourse text related to an imported image:

`![SH-MUniFrame.JPG|600x800](upload://6Li1nnjbA8zDz6YJ3FqeYHV5zXK.jpeg)`

The content of the “cooked” field:  
`<img src="https://global.discourse-cdn.com/meta/original/3X/0/3/0379f53ed8221730ccb31807238e9c46e9fe1d37.jpeg" alt="SH-MUniFrame.JPG" data-base62-sha1="6Li1nnjbA8zDz6YJ3FqeYHV5zXK" width="517" height="500" class="d-lazyload">`

How the image appears in: the post

 ![image](https://global.discourse-cdn.com/meta/original/3X/b/d/bdd2ab141ab2ca549d8e46ffa60c62573d17ed14.jpeg)  
Here is the original image: [https://global.discourse-cdn.com/meta/original/3X/f/7/f73a0ae8594219dd5a1620e59b3c17f9b02b1583.jpeg](https://global.discourse-cdn.com/meta/original/3X/f/7/f73a0ae8594219dd5a1620e59b3c17f9b02b1583.jpeg)

The original image size from the vBulletin database is:

```plaintext
select width, height from filedata where filedataid = 76237
+-------+--------+
| width | height |
+-------+--------+
| 600 | 800 |
+-------+--------+

```

My understanding is that the height attribute is constrained by Discourse’s setting which sets a max height of 500px, hence the same value in the `<img>` height attribute. The `<img>` width is somewhat modified from 600 to 517 though I can’t figure it how and why.

The issue is the same for older images that have 0 in both width and height vBulletin attachment fields. They also have the wrong height/width issue. I don’t know if these values are really used during the import.

The issue is resolved by rebaking (rebuild HTML) the post. the image will then be properly resized and the image viewer is added. But I have 1.6M posts and I’d prefer to avoid rebake all of them.

A quick fix would be to use this CSS on my Discourse:

```css
.cooked img:not(.emoji) {
    height: auto;
    width: auto;
}

```

But it implies that no one will be able to choose an arbitrary size when uploading an image, and there may be collateral effects I’m not aware of.

Why idea how I could have proper images width/height ratio on imported attachments?

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [22 augustus 2020 om 19:37 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/105 "2020-08-22T19:37:48Z")

</div>

I suspect that’s because you didn’t let them cook after the import. I cannot imagine a way to solve the problem without rebaking the posts. Perhaps you want to just rebake the posts that are broken rather than all of them?

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [22 augustus 2020 om 19:47 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/106 "2020-08-22T19:47:02Z")

</div>

Are they supposed to be cooked automatically over time after the import? Starting from the last or the first created post?

That’s not a big issue though, and if they are not automatically cooked, I’d probably start a rebake of all posts and be patient, although I admit that I read this post a few days ago and it scared me a little bit: [My journey into a massive posts rebake job](https://meta.discourse.org/t/my-journey-into-a-massive-posts-rebake-job/84816). I also have questions about that, but I’ll ask them in the proper topic. 😊

---

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [22 augustus 2020 om 20:10 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/107 "2020-08-22T20:10:32Z")

</div>

> [@Canapin](#):
>
> If I do this query in mysql, my remaining ram is filled within seconds.

Hmm yes that looks like it’s my code. Sorry for that. 😕

This should be following this pattern:

```
   batches(BATCH_SIZE) do |offset|
       (Sql code)
        LIMIT #{BATCH_SIZE}
        OFFSET #{offset}
        (Other code)
    end

```

---

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [22 augustus 2020 om 20:13 UTC](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881/108 "2020-08-22T20:13:37Z")

</div>

> [@Canapin](#):
>
> `Body is limited to 32000 characters`

Just raise the `max post length` site setting prior to the import.

[Vorige pagina](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881.md?page=4)

[Volgende pagina](https://meta.discourse.org/t/migrate-a-vbulletin-4-forum-to-discourse/54881.md?page=6)
