NationalSecurityAgency/ghidra · error · IOException
Multiple settings for:
Error message
Multiple settings for:
What it means
BSim's ServerConfig parser reads a server config file line by line, tracking recognized keys in a `keyValue` map. Each controlled setting key may be set at most once: when the parser encounters a key whose stored value is already non-empty, it throws IOException("Multiple settings for: " + key). This prevents ambiguous or contradictory configuration values.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ServerConfig.java:704
String line;
ConfigLine parse = new ConfigLine();
try {
for (;;) {
line = reader.readLine();
if (line == null) {
break; // End of file reached
}
if (line.length() != 0) {
parse.parseUptoKey(line);
if (parse.key == null) {
continue;
}
String curval = keyValue.get(parse.key); // Check if this is a key we want to find
if (curval != null) { // If this line is setting a value we control
if (curval.length() != 0) {
throw new IOException("Multiple settings for: " + parse.key);
}
parse.parseValue(line); // Discard the original value, but preserve any comment
if (parse.status == 1) { // We have uncommented controlled key
keyValue.put(parse.key, parse.value);
}
}
}
}
}
finally {
reader.close();
}
}
/**
* Read in all the entries of the connection file
* @param inFile the file to read in
* @throws IOException if the file cannot be read/parsedView on GitHub (pinned to d5f144c24d)
Solutions
- Read the trailing key name in the message and locate every occurrence of that directive in the config file.
- Delete the duplicate line(s), keeping a single canonical value.
- Restart the BSim server process so the parser re-reads the cleaned config.
- Add a pre-flight lint (grep for repeated keys) to CI for config files.
Example fix
# before port 8080 database bsim_primary port 9090 # duplicate -- remove # after port 8080 database bsim_primary
Defensive patterns
Strategy: validation
Validate before calling
// Before handing the file to ServerConfig, scan for duplicate controlled keys.
// (Adapt 'controlledKeys' to the set BSim recognizes: database, port, etc.)
Set<String> controlledKeys = Set.of("database", "port", "repository");
Map<String, Long> counts = new HashMap<>();
for (String line : Files.readAllLines(Path.of(confPath))) {
String[] kv = line.trim().split("\\s+", 2);
if (kv.length == 2 && controlledKeys.contains(kv[0]))
counts.merge(kv[0], 1L, Long::sum);
}
Map<String, Long> dups = counts.entrySet().stream()
.filter(e -> e.getValue() > 1)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if (!dups.isEmpty()) throw new IllegalStateException("Duplicate keys: " + dups); Try / catch
try {
ServerConfig.parse(confFile);
} catch (IOException e) {
if (e.getMessage().startsWith("Multiple settings for:")) {
// surface the duplicated key to the operator; do not retry
throw new ConfigException("Fix duplicate directive: " + e.getMessage(), e);
}
throw e;
} Prevention
- Keep a single canonical config file per BSim server; avoid merge-by-append.
- Lint config files in CI for repeated keys before deploy.
- Document each recognized key once and remove superseded lines on upgrade.
When it happens
Trigger: Editing a BSim server .conf (e.g. bsimserver.conf) and listing the same controlled directive twice, such as two `database`, `port`, or `repository` lines. The parser reaches the second assignment, sees `curval` is already populated, and throws.
Common situations: Hand-merging config snippets; copy-pasting a template block without deleting the original; appending new config during a version upgrade and leaving the old line in place; trailing duplicate from a bad sed/awk edit.
Related errors
- Parsing error
- Bad map field in pg_ident.conf entry
- Missing system-name in pg_ident.conf entry
- Entry missing ending quote in pg_ident.conf
- Missing role in pg_ident.conf entry
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/b14c511363117702.
Report an issue: GitHub.