{"record":{"id":"c1c56f849f651219","repo":"HMCL-dev/HMCL","slug":"unexpected-first-token-firsttoken","errorCode":null,"errorMessage":"\"Unexpected first token: \" + firstToken","messagePattern":"\"Unexpected first token: \" \\+ firstToken","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/ForgeOldModMetadata.java","lineNumber":146,"sourceCode":"        ZipArchiveEntry mcmod = tree.getEntry(\"mcmod.info\");\n        if (mcmod == null)\n            throw new IOException(\"File \" + modFile + \" is not a Forge mod.\");\n\n        List<ForgeOldModMetadata> modList;\n\n        try (var reader = tree.getBufferedReader(mcmod);\n             var jsonReader = new JsonReader(reader)) {\n            JsonToken firstToken = jsonReader.peek();\n\n            if (firstToken == JsonToken.BEGIN_ARRAY)\n                modList = JsonUtils.GSON.fromJson(jsonReader, listTypeOf(ForgeOldModMetadata.class));\n            else if (firstToken == JsonToken.BEGIN_OBJECT) {\n                ForgeOldModMetadataLst list = JsonUtils.GSON.fromJson(jsonReader, ForgeOldModMetadataLst.class);\n                if (list == null)\n                    throw new IOException(\"Mod \" + modFile + \" `mcmod.info` is malformed\");\n                modList = list.modList();\n            } else {\n                throw new JsonParseException(\"Unexpected first token: \" + firstToken);\n            }\n        }\n\n        if (modList == null || modList.isEmpty())\n            throw new IOException(\"Mod \" + modFile + \" `mcmod.info` is malformed\");\n        ForgeOldModMetadata metadata = modList.get(0);\n        String authors = metadata.getAuthor();\n        if (StringUtils.isBlank(authors) && metadata.getAuthors().length > 0)\n            authors = String.join(\", \", metadata.getAuthors());\n        if (StringUtils.isBlank(authors) && metadata.getAuthorList().length > 0)\n            authors = String.join(\", \", metadata.getAuthorList());\n        if (StringUtils.isBlank(authors))\n            authors = metadata.getCredits();\n        return new LocalModFile(modManager, modManager.getLocalMod(metadata.getModId(), ModLoaderType.FORGE), modFile, metadata.getName(), new LocalAddonFile.Description(metadata.getDescription()),\n                authors, metadata.getVersion(), metadata.getGameVersion(),\n                StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url,\n                metadata.getLogoFile());\n    }","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/ForgeOldModMetadata.java#L128-L164","documentation":"ForgeOldModMetadata.fromFile expects `mcmod.info` to start with either a JSON array (a mod list) or an object (`{\"modList\": ...}`). Any other leading token (string, number, boolean, END) triggers a JsonParseException naming the unexpected token.","triggerScenarios":"Calling ForgeOldModMetadata.fromFile on a jar whose `mcmod.info` begins with a scalar like `\"foo\"`, `42`, or `true` instead of an array or object.","commonSituations":"Placeholder `mcmod.info` files written by hand; build scripts accidentally embedding a plain string; truncation leaving a partial scalar.","solutions":["Inspect `mcmod.info` in the jar and make the root a JSON array or an object with `modList`","Re-obtain the mod jar from its official release","Exclude the jar from scanning if it is not a Forge mod"],"exampleFix":"// before (invalid root)\n\"not a mod list\"\n// after\n[{ \"modid\": \"example\", \"name\": \"Example\", \"version\": \"1.0\" }]","handlingStrategy":"validation","validationCode":"String s = readMcmodInfo(tree);\nString t = s.trim();\nif (!(t.startsWith(\"[\") || t.startsWith(\"{\")))\n    throw new IllegalStateException(\"mcmod.info must start with '[' or '{'\");","typeGuard":null,"tryCatchPattern":"try {\n    ForgeOldModMetadata.fromFile(modManager, modFile, tree);\n} catch (JsonParseException e) {\n    log.warn(\"Unexpected mcmod.info structure: \" + e.getMessage());\n}","preventionTips":["Validate JSON root type with a quick peek at the first non-whitespace char","Keep build-tool metadata generation enabled","Sanity-check packaged resources in CI"],"tags":["java","json","mod-metadata","gson"],"backgroundTag":"invalid-json-response","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}