{"record":{"id":"392bac7fd979901d","repo":"NationalSecurityAgency/ghidra","slug":"score-file-missing-threshold-lines","errorCode":null,"errorMessage":"Score file missing threshold lines","messagePattern":"Score file missing threshold lines","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/FileScoreCaching.java","lineNumber":50,"sourceCode":"\t\tstorageFile = new File(fileName);\n\t\tcacheMap = null;\n\t\tsimThreshold = -1.0;\t\t// Negative indicates thresholds have not been configured\n\t\tsigThreshold = -1.0;\n\t}\n\n\tprivate void loadCache() throws IOException {\n\t\tif (cacheMap != null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!storageFile.exists()) {\n\t\t\treturn;\t\t\t\t\t\t\t// File doesn't exist, it will get created on first commitSelfScore call\n\t\t}\n\t\tcacheMap = new TreeMap<String, Float>();\n\t\tBufferedReader reader = new BufferedReader(new FileReader(storageFile));\n\t\tString floatString = reader.readLine();\n\t\tif (floatString == null) {\n\t\t\treader.close();\n\t\t\tthrow new IOException(\"Score file missing threshold lines\");\n\t\t}\n\t\tsimThreshold = Float.parseFloat(floatString);\n\t\tfloatString = reader.readLine();\n\t\tif (floatString == null) {\n\t\t\treader.close();\n\t\t\tthrow new IOException(\"Score file missing threshold lines\");\n\t\t}\n\t\tsigThreshold = Float.parseFloat(floatString);\n\t\tfloatString = reader.readLine();\n\t\twhile (floatString != null) {\n\t\t\tString[] split = floatString.split(\" \");\n\t\t\tif (split.length != 2 || split[0].length() != 32) {\n\t\t\t\treader.close();\n\t\t\t\tthrow new IOException(\"Bad line in score file\");\n\t\t\t}\n\t\t\tfloat val = Float.parseFloat(split[1]);\n\t\t\tcacheMap.put(split[0], val);\n\t\t\tfloatString = reader.readLine();","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/FileScoreCaching.java#L32-L68","documentation":"Thrown by FileScoreCaching.loadCache() when the score file exists but is completely empty — the first readLine() returns null. The expected file format begins with two header lines (simThreshold then sigThreshold) followed by one line per executable (md5 + score). An empty or zero-byte file fails this invariant at the very first read.","triggerScenarios":"The score cache file referenced by FileScoreCaching's constructor exists on disk but contains no data (e.g. created by a failed/touch command, truncated by a crash during write, or a race condition where the file was created but the header lines were never flushed).","commonSituations":"An interrupted previous run left a zero-byte cache file. A user manually created or truncated the cache file. A concurrent process or filesystem issue truncated the file between the existence check and the read.","solutions":["Delete the corrupt/empty cache file so it gets regenerated with valid header lines on the next commitSelfScore call.","Call FileScoreCaching.resetStorage(simThresh, sigThresh) to delete the existing file and reinitialize thresholds.","Investigate what created the empty file (failed process, manual touch) to prevent recurrence."],"exampleFix":"// before — cache file exists but is empty\nFileScoreCaching cache = new FileScoreCaching(path);\ncache.getSelfScore(md5); // throws IOException \"Score file missing threshold lines\"\n\n// after\nFileScoreCaching cache = new FileScoreCaching(path);\ncache.resetStorage(simThresh, sigThresh); // deletes bad file, resets thresholds","handlingStrategy":"validation","validationCode":"File cacheFile = new File(cachePath);\nif (cacheFile.exists() && cacheFile.length() == 0) {\n    cacheFile.delete(); // remove empty file so it regenerates\n}","typeGuard":null,"tryCatchPattern":"try {\n    cache.getSelfScore(md5);\n} catch (LSHException e) {\n    if (e.getMessage().contains(\"threshold lines\")) {\n        cache.resetStorage(simThresh, sigThresh);\n        // regenerate scores then retry\n    } else throw e;\n}","preventionTips":["Validate the cache file has content before relying on it.","Use resetStorage to clean corrupt files.","Investigate what left the file empty (crashed process, manual touch)."],"tags":["bsim","ghidra","score-cache","file-format","corruption"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}