Deleting files via the API using =.id=*ABCD0123

There’s some odd behavior when using the API to list files and delete files on MikroTik a device (a RB433AH in this case, running OS 4.4 with firmware 2.23). If I execute by API a ‘/file/getall’ to list the files, the execute a ‘/file/remove’ and remove one of those files, then execute a second ‘/file/remove’ to remove another file (both using the file .id), the second one often fails with a trap.

But after that trap, if I do a new ‘/file/getall’, the second file I tried to delete has the exact same .id, and if I now attempt to remove it with ‘/file/remove’ (again by .id), it succeeds.

I thought the entire point of using .id in the API was that the IDs are globally unique to the device and do not change, so one is safe to refer to the object in question by ID with API commands.

My question: Why on earth must I re-execute ‘/file/getall’ after each file deletion just to avoid file removal failure?

In the API session output below, note that the device has two files, “foobar5.html” and “foobar3.html” that I wish to delete. Note also that the .id attributes of each file NEVER change over the course of the API session. Note finally that of the two exactly identical “/file/remove” commands attempting to remove file “foobar5.html” (with ID *1F010320), the first fails, but the second succeeds.

Why is that? (Why does one command fail, but the subsequent one succeeds when they are identical in every way?)

Here’s my API session in question:

Command (/quit to end): /file/getall
=== COMMAND: /file/getall
<<< '/file/getall' (12)
<<< '.tag=15' (7)
<<< END-OF-SENTENCE

>>> '!re' (3)
>>> '.id=*1F010320' (13)
>>> 'name=foobar5.html' (17)
>>> 'type=.html file' (15)
>>> 'size=440' (8)
>>> 'creation-time=jan/15/2010 15:20:47' (34)
>>> 'contents=<?xml version="1.0" encoding="utf-8"?>' (47)
>>> '.tag=15' (7)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> '.id=*1F010416' (13)
>>> 'name=foobar3.html' (17)
>>> 'type=.html file' (15)
>>> 'size=440' (8)
>>> 'creation-time=jan/15/2010 15:18:57' (34)
>>> 'contents=<?xml version="1.0" encoding="utf-8"?>' (47)
>>> '.tag=15' (7)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=15' (7)
>>> END-OF SENTENCE

Great, I now have a list of files on the device: “foobar5.html” (ID *1F010320) and “foobar3.html” (ID *1F010416).

Next I try deleting the second of the two, “foobar3.html” using the file’s object ID *1F010416:

Command (/quit to end): /file/remove =.id=*1F010416
=== COMMAND: /file/remove
<<< '/file/remove' (12)
<<< '=.id=*1F010416' (14)
<<< '.tag=16' (7)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> '.tag=16' (7)
>>> END-OF SENTENCE

Great! It looks like that worked! So I immediately try to remove the first file, “foobar5.html” with ID *1F010320:

Command (/quit to end): /file/remove =.id=*1F010320
=== COMMAND: /file/remove
<<< '/file/remove' (12)
<<< '=.id=*1F010320' (14)
<<< '.tag=17' (7)
<<< END-OF-SENTENCE

>>> '!trap' (5)
>>> 'category=4' (10)
>>> 'message=no such item (4)' (24)
>>> '.tag=17' (7)
>>> END-OF SENTENCE

=== TRAP: 'no such item (4)'

>>> '!done' (5)
>>> '.tag=17' (7)
>>> END-OF SENTENCE

Whoa! What’s going on here? Did removing “foobar3.html” somehow cause the object ID of “foobar5.html” to change? Wondering this, I checked:

Command (/quit to end): /file/getall
=== COMMAND: /file/getall
<<< '/file/getall' (12)
<<< '.tag=18' (7)
<<< END-OF-SENTENCE

>>> '!re' (3)
>>> '.id=*1F010320' (13)
>>> 'name=foobar5.html' (17)
>>> 'type=.html file' (15)
>>> 'size=440' (8)
>>> 'creation-time=jan/15/2010 15:20:47' (34)
>>> 'contents=<?xml version="1.0" encoding="utf-8"?>' (47)
>>> '.tag=18' (7)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=18' (7)
>>> END-OF SENTENCE

Nope, there it is: “foobar5.html” with the exact same ID *1F010320 as before. So I execute the EXACT SAME API COMMAND as before:

Command (/quit to end): /file/remove =.id=*1F010320
=== COMMAND: /file/remove
<<< '/file/remove' (12)
<<< '=.id=*1F010320' (14)
<<< '.tag=19' (7)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> '.tag=19' (7)
>>> END-OF SENTENCE

That one works! And it is byte-for-byte-on-the-wire identical (save for the command tag which is irrelevant) to the first attempt to remove the file. I’m really puzzled.

Thanks in advance for any ideas!

Aaron out.

huh… probably you’re lucky, but I didn’t even succeed in executing of first ‘remove =.id=*NNN’ - it says ‘no such item (4)’ =) but this one works fine:

/file/remove
=numbers=*123,*456,*789

all three files gets deleted at once. and even one-by-one :slight_smile:

I tested with v4.5

hmm, tried it - and it is working on 4.5 please do the upgrade.

if after upgrade you encounter same behavior you described it would be nice if you could write to support@mikrotik if possible with details on how to connect to that router to test that out