{"record":{"id":"87d7cae3685fb5b7","repo":"fatedier/frp","slug":"failed-to-parse-json-w","errorCode":null,"errorMessage":"failed to parse JSON: %w","messagePattern":"failed to parse JSON: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/source/store.go","lineNumber":88,"sourceCode":"func (s *StoreSource) loadFromFile() error {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn s.loadFromFileUnlocked()\n}\n\nfunc (s *StoreSource) loadFromFileUnlocked() error {\n\tdata, err := os.ReadFile(s.config.Path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttype rawStoreData struct {\n\t\tProxies  []jsonx.RawMessage `json:\"proxies,omitempty\"`\n\t\tVisitors []jsonx.RawMessage `json:\"visitors,omitempty\"`\n\t}\n\tstored := rawStoreData{}\n\tif err := jsonx.Unmarshal(data, &stored); err != nil {\n\t\treturn fmt.Errorf(\"failed to parse JSON: %w\", err)\n\t}\n\n\ts.proxies = make(map[string]v1.ProxyConfigurer)\n\ts.visitors = make(map[string]v1.VisitorConfigurer)\n\n\tfor i, proxyData := range stored.Proxies {\n\t\tproxyCfg, err := v1.DecodeProxyConfigurerJSON(proxyData, v1.DecodeOptions{\n\t\t\tDisallowUnknownFields: false,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to decode proxy at index %d: %w\", i, err)\n\t\t}\n\t\tname := proxyCfg.GetBaseConfig().Name\n\t\tif name == \"\" {\n\t\t\treturn fmt.Errorf(\"proxy name cannot be empty\")\n\t\t}\n\t\ts.proxies[name] = proxyCfg\n\t}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/source/store.go#L70-L106","documentation":"loadFromFileUnlocked read the store file successfully but its contents are not valid JSON, so jsonx.Unmarshal into the raw {proxies, visitors} envelope failed. The store file must be a JSON object whose proxies/visitors members are arrays; any syntax error anywhere in the file produces this error.","triggerScenarios":"The store file was hand-edited and contains a trailing comma, unquoted key, or comment; the file was truncated by an external process (this library itself writes atomically via temp-file + rename, so self-inflicted truncation is unlikely); an empty (0-byte) file also fails JSON parsing; a file with a UTF-8 BOM or C2 A0 characters pasted from a rich-text editor.","commonSituations":"Manually tweaking the generated store JSON instead of using the API; a git merge conflict resolved badly on a committed store file; a partially synced/copied file between hosts; running an old frp version that wrote a non-JSON format (e.g. TOML/INI) at the same path.","solutions":["Validate the file offline: jq . <path> — jq pinpoints the line/column of the syntax error","Fix the reported syntax issue (trailing comma, missing quote, comment) and retry NewStoreSource","If the file is unusable, restore it from backup or VCS history (git checkout -- store.json)","As a last resort, move the file aside (mv store.json store.json.bak) to start with an empty store, then re-add proxies/visitors through the API"],"exampleFix":"// before: file content\n{ \"proxies\": [ {\"type\":\"tcp\",\"name\":\"web\"}, ], }\n\n// after: valid JSON\n{ \"proxies\": [ {\"type\":\"tcp\",\"name\":\"web\"} ] }","handlingStrategy":"validation","validationCode":"func validateStoreJSON(path string) error {\n\tdata, err := os.ReadFile(path)\n\tif errors.Is(err, fs.ErrNotExist) {\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !json.Valid(data) {\n\t\treturn fmt.Errorf(\"store file %s is not valid JSON\", path)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"src, err := source.NewStoreSource(cfg)\nif err != nil && strings.Contains(err.Error(), \"failed to parse JSON\") {\n\t// quarantine the bad file and start empty (accepting data loss) or restore from backup\n\t_ = os.Rename(cfg.Path, cfg.Path+\".corrupt\")\n}","preventionTips":["Never hand-edit the generated store file; use the Add/Update/Remove API","If the file is under VCS, run a pre-commit hook with jq . to catch syntax errors","Back up the store before upgrades that change its format"],"tags":["json","config","corruption","parsing","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}