{"record":{"id":"b963bdaa41359c93","repo":"LaurieWired/GhidraMCP","slug":"unknown-type-typename-defaulting-to-int","errorCode":null,"errorMessage":"Unknown type: \" + typeName + \", defaulting to int","messagePattern":"Unknown type: \" \\+ typeName \\+ \", defaulting to int","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/java/com/lauriewired/GhidraMCPPlugin.java","lineNumber":1490,"sourceCode":"            case \"__int64\":\n                return dtm.getDataType(\"/longlong\");\n            case \"ulonglong\":\n            case \"unsigned __int64\":\n                return dtm.getDataType(\"/ulonglong\");\n            case \"bool\":\n            case \"boolean\":\n                return dtm.getDataType(\"/bool\");\n            case \"void\":\n                return dtm.getDataType(\"/void\");\n            default:\n                // Try as a direct path\n                DataType directType = dtm.getDataType(\"/\" + typeName);\n                if (directType != null) {\n                    return directType;\n                }\n\n                // Fallback to int if we couldn't find it\n                Msg.warn(this, \"Unknown type: \" + typeName + \", defaulting to int\");\n                return dtm.getDataType(\"/int\");\n        }\n    }\n    \n    /**\n     * Find a data type by name in all categories/folders of the data type manager\n     * This searches through all categories rather than just the root\n     */\n    private DataType findDataTypeByNameInAllCategories(DataTypeManager dtm, String typeName) {\n        // Try exact match first\n        DataType result = searchByNameInAllCategories(dtm, typeName);\n        if (result != null) {\n            return result;\n        }\n\n        // Try lowercase\n        return searchByNameInAllCategories(dtm, typeName.toLowerCase());\n    }","sourceCodeStart":1472,"sourceCodeEnd":1508,"githubUrl":"https://github.com/LaurieWired/GhidraMCP/blob/27f316f80139e2d5dec882519a1bdf4aa46ac04c/src/main/java/com/lauriewired/GhidraMCPPlugin.java#L1472-L1508","documentation":"A warning (not an exception) logged in the built-in-type fallback branch of GhidraMCPPlugin's type-string parser. After the pointer/array handling and a direct root-path lookup via dtm.getDataType(\"/\" + typeName) both fail, the parser logs 'Unknown type' and returns the '/int' data type as a silent default. It signals that a type name supplied to (or emitted by) a tool could not be resolved in the program's data type manager.","triggerScenarios":"Calling a plugin endpoint that accepts a type-name string (e.g. create-struct or apply-type tooling) with a name that is neither a recognized built-in keyword in the parser's switch nor an existing data type at the DTM root path ('/' + typeName). Typical inputs: 'uint32', 'DWORD', 'LPSTR', or a struct name that was never defined in this program.","commonSituations":"Users pass Windows/SDK type names or language typedefs that Ghidra does not define by default; programs analyzed without the appropriate GDT archives loaded; scripts/tools receiving types from decompiler output of an uninitialized header set — resulting fields are silently typed as int.","solutions":["Load the correct data type archive (File > Configure/parse headers, or attach a .gdt) so the named type exists, then re-run.","Use the exact built-in names the parser's switch recognizes (e.g. 'int', 'char', 'void', 'unsigned int' lowercased) instead of platform typedefs like 'DWORD' or 'uint32'.","Create the missing type in the Data Type Manager before invoking the tool so dtm.getDataType(\"/\" + typeName) succeeds.","Patch the parser to map common typedefs (uint32->int, DWORD->int) instead of blind int fallback if you control the plugin code."],"exampleFix":"// before\nDataType directType = dtm.getDataType(\"/\" + typeName);\nif (directType != null) {\n    return directType;\n}\nMsg.warn(this, \"Unknown type: \" + typeName + \", defaulting to int\");\nreturn dtm.getDataType(\"/int\");\n// after\nDataType directType = dtm.getDataType(\"/\" + typeName);\nif (directType != null) {\n    return directType;\n}\nDataType aliased = resolveTypedef(typeName); // map uint32/DWORD/etc. to built-ins\nif (aliased != null) {\n    return aliased;\n}\nMsg.warn(this, \"Unknown type: \" + typeName + \", defaulting to int\");\nreturn dtm.getDataType(\"/int\");","handlingStrategy":"validation","validationCode":"// Client-side check before sending a type name to the plugin\nSet<String> builtins = Set.of(\"int\", \"char\", \"void\", \"unsigned int\", \"long\",\n    \"short\", \"float\", \"double\", \"unsigned char\", \"unsigned long\", \"unsigned short\");\nboolean known = builtins.contains(typeName.toLowerCase())\n    || currentProgram.getDataTypeManager().getDataType(\"/\" + typeName) != null;\nif (!known) {\n    throw new IllegalArgumentException(\"Type '\" + typeName + \"' is not a built-in and \"\n        + \"does not exist in the Data Type Manager; define or import it first.\");\n}","typeGuard":"function isResolvableType(program, typeName) {\n    const dtm = program.getDataTypeManager();\n    return BUILTIN_NAMES.includes(typeName.toLowerCase())\n        || dtm.getDataType('/' + typeName) !== null;\n}","tryCatchPattern":null,"preventionTips":["Only pass type names that exist in the program's Data Type Manager or the parser's built-in switch (lowercase C keywords).","Load standard header/GDT archives (windows, posix) before analysis so common typedefs resolve.","Prefer canonical Ghidra type names ('unsigned int') over platform typedefs ('DWORD', 'uint32').","After tool calls, inspect generated structures for unexpected int fields — they indicate this fallback fired."],"tags":["ghidra","java","type-lookup","fallback","dtm"],"backgroundTag":"resource-not-found","analyzedSha":"27f316f80139e2d5dec882519a1bdf4aa46ac04c","analyzedAt":"2026-09-10T10:08:33.079Z","contentChangedAt":"2026-09-10T10:08:33.079Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}