{"record":{"id":"4708ce92d291bcfe","repo":"hashicorp/nomad","slug":"recovery-failed-to-parse-peers-json-v","errorCode":null,"errorMessage":"recovery failed to parse peers.json: %v","messagePattern":"recovery failed to parse peers\\.json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/server.go","lineNumber":1557,"sourceCode":"\n\t\t\t// Blow away the peers.json file if present, since the\n\t\t\t// peers.info sentinel wasn't there.\n\t\t\tif _, err := os.Stat(peersFile); err == nil {\n\t\t\t\tif err := os.Remove(peersFile); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to delete peers.json, please delete manually (see peers.info for details): %v\", err)\n\t\t\t\t}\n\t\t\t\ts.logger.Info(\"deleted peers.json file (see peers.info for details)\")\n\t\t\t}\n\t\t} else if _, err := os.Stat(peersFile); err == nil {\n\t\t\ts.logger.Info(\"found peers.json file, recovering Raft configuration...\")\n\t\t\tvar configuration raft.Configuration\n\t\t\tif s.config.RaftConfig.ProtocolVersion < 3 {\n\t\t\t\tconfiguration, err = raft.ReadPeersJSON(peersFile)\n\t\t\t} else {\n\t\t\t\tconfiguration, err = raft.ReadConfigJSON(peersFile)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"recovery failed to parse peers.json: %v\", err)\n\t\t\t}\n\t\t\ttmpFsm, err := NewFSM(fsmConfig)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"recovery failed to make temp FSM: %v\", err)\n\t\t\t}\n\t\t\tif err := raft.RecoverCluster(s.config.RaftConfig, tmpFsm,\n\t\t\t\tlog, stable, snap, trans, configuration); err != nil {\n\t\t\t\treturn fmt.Errorf(\"recovery failed: %v\", err)\n\t\t\t}\n\t\t\tif err := os.Remove(peersFile); err != nil {\n\t\t\t\treturn fmt.Errorf(\"recovery failed to delete peers.json, please delete manually (see peers.info for details): %v\", err)\n\t\t\t}\n\t\t\ts.logger.Info(\"deleted peers.json file after successful recovery\")\n\t\t}\n\t}\n\n\t// If we are a single server cluster and the state is clean then we can\n\t// bootstrap now.","sourceCodeStart":1539,"sourceCodeEnd":1575,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/server.go#L1539-L1575","documentation":"When recovering Raft configuration from a manually supplied peers.json, Nomad parses it with raft.ReadPeersJSON (protocol < 3) or raft.ReadConfigJSON (>= 3). This error wraps the parse failure, meaning the file is missing, unreadable, or not valid JSON in the expected peer-list/configuration format.","triggerScenarios":"Server start with peers.json present and no peers.info, and the file cannot be read/parsed — wrong JSON schema (e.g. old flat array vs raft.Configuration object), trailing garbage, wrong protocol-version format, or missing file mid-flight.","commonSituations":"Operator hand-edited peers.json and broke the syntax; copied a pre-0.8 format peers.json into a modern Nomad (needs raft.Configuration format with ProtocolVersion >= 3); protocol_version config mismatch with the file's format; file truncated during copy.","solutions":["Validate peers.json is correct JSON in the format matching your raft protocol version (raft.Configuration object for protocol >= 3, e.g. {\"server_id\":\"...\",\"server_addr\":\"...\"} entries under \"Servers\")","For Nomad >= 0.8 use the raft Configuration JSON format, not the legacy flat peer list","Recreate the file from the documented template with the current cluster server IDs and addresses","Ensure the file is readable by the Nomad user and not truncated (cat the file, run it through jq)"],"exampleFix":"// before (legacy format)\n[\"10.0.0.1:4647\",\"10.0.0.2:4647\"]\n// after (raft.Configuration format, protocol >= 3)\n{\"Servers\":[{\"ID\":\"7e4e2d0a-...\",\"Address\":\"10.0.0.1:4647\"},{\"ID\":\"a1b2c3d4-...\",\"Address\":\"10.0.0.2:4647\"}]}","handlingStrategy":"validation","validationCode":"// Validate peers.json parses and has the expected shape before restart\nconst cfg = JSON.parse(fs.readFileSync(dataDir + '/peers.json', 'utf8'));\nif (!Array.isArray(cfg.Servers) || cfg.Servers.length === 0)\n  throw new Error('peers.json must be a raft.Configuration with a non-empty Servers array (protocol >= 3)');\nfor (const s of cfg.Servers) if (!s.ID || !s.Address) throw new Error('each server needs ID and Address');","typeGuard":null,"tryCatchPattern":"try {\n  startNomadServer();\n} catch (e) {\n  if (String(e).includes('recovery failed to parse peers.json')) {\n    console.error('Fix peers.json format:', e.message);\n  }\n  throw e;\n}","preventionTips":["Use the raft.Configuration JSON format ({\"Servers\":[{ID,Address}]}) for Nomad >= 0.8, not the legacy list","Never hand-edit the file without validating with jq","Match the file format to your configured raft protocol_version"],"tags":["raft","recovery","json","configuration"],"backgroundTag":"raft-peers-json-recovery","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}