Debug a needle in a haystack

You probably know the problem. You have to find where some field is updated in the application and you haven’t the slightest idea where the crime is happening. This can easily happen with big add-ons that you don’t know and if things really go bad, there might be multiple places where the table (and the incriminating field) is updated but you don’t know where and there are also a lot of places where the table and field are referenced so searching for “Record xxxx” is long.

My old trick was to rename the field to something that was definitely unique in the database like “Incriminating Field”. Export all objects as text and search for it. This could get quite long especially if you have to filter out objects for which you don’t have read-permissions. You get the error only when NAV tries to export it. Generally after exporting all the rest.

Now starting with NAV2013, there is another option using the debugger in a smart way. No, it doesn’t mean doing step-by-step debugging until you find the offending code.

This is the way I do it:

First enable change log and enable the logging for insert/modify of the incriminating table in which the incriminating field is hiding and do it ONLY FOR THAT TABLE!

Restart the client sessions to enable the logging (NAV runs function C1.GetDatabaseTableTriggerSetup() only once per table to check if it needs to run the other triggers or not. This function is executed the first time an insert/Modify/Delete/Rename is run.

Put a breakpoint in codeunit 423:”Change Log Management”.LogModification (or LogInsertion).

Let the debugger get to the function.

Put a watch on “RecRef.Fields.YourField” and “xRecRef.Fields.YourField”. When the break stops there, you can easily see the old and new values of the field and decide if it is the change you were looking for. In the call stack you can see what objects and functions have been called and where the value was changed.

You might also put some code in the function to put the record in a variable and then put a conditional break on it but this means you have to change the code which I prefer to avoid.


Really big temptable in PRE-NAV2013 and NAV2013+

I have to admit I had some doubts about the title. I was first thinking about “An attempt was made to move the file pointer before the beginning of the file.” but that would exclude a little bit also referring to NAV2013+ (I explain this in the second part of this blogpost). And I was more interested in what would happen in NAV2013+ with a 64 bit servicetier created from scratch.

So this blogpost has to subtopics in it: One talking about PRE-NAV2013 and another about NAV2013+.

  • PRE-NAV2013 (tested with NAV2009R2)

If you have a really big temptable, at a certain point you might hit this error:


Microsoft Dynamics NAV Classic


The operating system returned the error (131):

An attempt was made to move the file pointer before the beginning of the file.


Why? What does this mean?

First and for all. A temptable starts in memory and when it gets a bit bigger, it is written to a file. How big? I don’t know, but this is not important here.

PRE-NAV2013 is using a 4 byte signed integer to keep track the size of the file. Why not a biginteger? That is an inheritance of the old FAT ( and DOS ( Basically, a file was limited to max 2GB of size. And a 4 byte integer goes from −2 147 483 648 to 2 147 483 647, so a perfect match.

But with the later FAT implementations or NTFS (, we don’t have that 2G file limit anymore. But it is still there in PRE-NAV2013.

So when NAV is writing to the file, at a certain point it gets over the 2GB size and the integer used to track the size becomes negative, generating the above error (and crashing the native client, but that is not important here [well… kind of…]).

To create the problem, I have created a table with an integer as primary key and 4 Text250-fields. The following code fills up the temptable until it hits the error. The same code I also used in NAV2013+.

This is the code I used to fill up the temptable. I put the code in a codeunit.


t99915.t1 := PADSTR(”,250,’x’);

t99915.t2 := t99915.t1;

t99915.t3 := t99915.t1;

t99915.t4 := t99915.t1;

FOR i := 1 TO 5000000 DO BEGIN

IF i MOD 1000 = 0 THEN

dia.UPDATE(1,i); := i;





How to avoid this error? There are a few things you can try:

-If you are using a standard table, you can create your own table tailored to your needs. It is not necessary to put it in the license if you only use the table only as a temptable. Put only the fields in it that you need and only the sizes you need and limit SIFT-fields and extra keys as much as possible.

-Divide the records in the temptable over multiple temptables (Arrays on a temptable do not help because it points to the same temptable and not to different ones). Each temptable has its own file in the operating system, so you have multiple times 2 GB of data.

This was tested on a classic client and not on the 2009R2 RTC but I think it has the same problem.

  • NAV2013+

Does NAV2013+ still have this problem? The short answer is no. And I could finish the blogpost now, but I want to point out some details on what is going on.

-First good surprise is that it is a lot faster than with the older versions. This is because it does not write the data to disk, but keeps it in memory.

-Next good thing is that I don’t get the error anymore like I expected because it is all in memory now.

-But because everything is in memory, the service tier is gobbling up your precious memory. So you might run into out-of-memory issues. But on the positive side I did notice that the memory structure of a NAV2013+ temptable is more memory efficient than the file structure of a PRE-NAV2013 temptable. Meaning that a 2 GB file-structure in PRE-NAV2013 does NOT take 2 GB of memory in NAV2013+. I didn’t measure it scientifically but my guess is that it takes around 600MB to 1000 MB of memory instead of 2GB.

One other interesting observation I found is this:

Running the codeunit multiple times, memory increases to a few GB, but suddenly it releases memory to get under 1 GB. Looks like garbage collection kicking in.

Timestamp field in SQL and NAV2016

In SQL you have the timestamp field. Each table in NAV has it, but it is not shown in NAV. In NAV2016 you have the possibility to show it as you probably already found out.

Important to know is that the timestamp field does NOT contain a time in it (talking about a bad name for a field…). It is just some versioning ID. Each time a record is inserted/updated, it the value is increased by 1. But not necessary for the same record. I have noticed that a value “x” is used only once for a record in the whole database! This means that there is max 1 record in the whole database with a certain timestamp value (if you update the record, it will get a new timestamp value and the old timestamp value will disappear from the database).

So when you need to know the records that where changed, get the records with a timestamp larger than the largest one that you found last time (you will need to save that value somewhere).

I did a small test:

I created a key on the timestamp-field (I gave it a different name (not “timestamp”)) and that was not a problem.

Not having a key on the field will mean that SQL has to scan the whole table to find the records you are searching for.

New Blog

I know. I know. It has been too long that I have blogged since the mibuso website has been transferred.

I still have to transfer my old blogs to the new website, but that will take some more time.

I’ll start with some new blogs.