Troubleshooting

Why a MIB will not load

Could not load module at /path/to/VENDOR-MIB is the same sentence for a missing file, a PDF, a syntax error on line 412 and an IMPORTS clause that cannot be satisfied. Four unrelated problems, one message. Here is how to tell them apart.

This page describes the errors any SMIv2 tool produces, because they nearly all use the same parser underneath. SnmpLens reports the underlying cause directly — see what it shows instead at the end.

Why the message says nothing

The library most tools use to read MIBs, gosmi, wraps libsmi's model. When it cannot load a module it returns Could not load module at X — and it does so after having already computed a precise error and thrown it away. Inside, the real message reads like Parse module: VENDOR-MIB:412:7: unexpected "(". It is printed to standard output with fmt.Println and the function returns an empty string.

So the tool showing you Could not load module is not being unhelpful on purpose. It never received anything better. That is why the same sentence covers everything below.

First: is the file actually a MIB?

This is the most common cause by a wide margin, and the least suspected — because the file has the right name and a plausible size. Four downloads go wrong in the same way:

Files that are commonly mistaken for MIBs, and how to recognise each
What you actually haveHow to tellWhat to do
The web page around the file It begins with <!DOCTYPE html or <html The download returned the page, not the file. Use the raw or download link.
A PDF of the specification The first bytes are %PDF- MIBs are plain text. Extract the module from the document, or find the .mib.
A zip or gzip nobody extracted It starts with PK, or with the two bytes 1f 8b Extract it and import the files inside.
UTF-16 text A byte-order mark ff fe or fe ff, and NUL bytes throughout Save it as UTF-8 or ASCII. MIB parsers do not accept UTF-16.

A quick check on any platform, before blaming the syntax:

head -c 200 VENDOR-MIB

A MIB begins with a module name and the word DEFINITIONS, usually within the first few lines — though vendor files often carry several kilobytes of licence header first, so look further than the first screen before concluding.

Second: the file name is not the module name

A MIB declares its own name on its first meaningful line:

VENDOR-POWER-MIB DEFINITIONS ::= BEGIN

That declared name — VENDOR-POWER-MIB — is what every IMPORTS clause in every other file will look for, and it is what the loader looks up by file name. If the file is called vendor_power.txt or VENDOR-POWER-MIB.my, the module itself loads perfectly well when you point at it directly, and is invisible to anything that imports it.

This one is nasty because nothing is broken. The file is valid, it loads, and the failure appears in a different file — the one whose IMPORTS cannot be satisfied. Rename the file to the declared module name, with no extension or a consistent one.

Third: an IMPORTS clause that cannot be satisfied

A vendor MIB rarely stands alone. It imports from SNMPv2-SMI, SNMPv2-TC, often INET-ADDRESS-MIB, and frequently from the vendor's own root MIB, which is a separate download people miss:

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, Integer32   FROM SNMPv2-SMI
    DisplayString                             FROM SNMPv2-TC
    vendorProducts                            FROM VENDOR-SMI;

Missing VENDOR-SMI and the whole file fails, with a message naming neither the module nor the symbol. Three different situations produce it, and they need different answers:

Fourth: it loaded, and it is still wrong

This is the case that wastes the most time, because every indicator says success.

Imports are resolved lazily. A module that imports something unavailable can report a successful load and simply resolve those symbols to nothing. Worse, a file declaring a typo such as SYNTAX Integerr32and assigning the same OID twice — loads with no error at all: the type is looked up, nothing is found, and the object is added anyway with a nil type and an empty OID.

The symptom is not an error. It is an OID that translates to nothing, a table with no columns, or a name that resolves to iso — because asking for an unknown OID returns the closest known ancestor rather than failing.

What SnmpLens reports instead

SnmpLens captures the message the library discards and reports a stage — how far the file got before something stopped it:

The stages a MIB passes through, and what each failure means
StageWhat it means
readThe bytes could not be obtained — missing, unreadable, a directory.
contentThe bytes are not a MIB. This is the PDF, the HTML page, the zip.
parseThe grammar rejected it, with a line and a column.
importsIt needs a module that is not here, named, with the symbols it wanted.
buildRefused for another reason, with whatever the library actually said.
semanticIt loaded and resolves to nonsense — unknown types, duplicate OIDs.
loadedIt is in the tree.

With the stage come the things that make it actionable:

Diagnosis is offered on files that loaded too, for the reason in the fourth case above: success is not proof. And it only ever reads — it never loads modules as a side effect, because an explanation that quietly re-enables a MIB you switched off changes the answers every other lookup gives.

Try it against your own file.

Drop a MIB onto the window, or open the MIB editor. There is also a browser demo if you would rather not install anything first. Download SnmpLens — free, MIT licensed, Windows, macOS and Linux.

The short version

  1. Look at the first bytes. Is it text, and does it contain DEFINITIONS?
  2. Does the file name match the module the file declares?
  3. Read the IMPORTS clause. Is every module named there present and enabled?
  4. If it loads but resolves to nothing, suspect an unknown type or a duplicated OID — not the loader.

More on the MIB directory, importing and the editor in the documentation.