{"record":{"id":"cfbf23f5c6e4b2e4","repo":"fatedier/frp","slug":"failed-to-decode-visitor-at-index-d-w","errorCode":null,"errorMessage":"failed to decode visitor at index %d: %w","messagePattern":"failed to decode visitor at index (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/source/store.go","lineNumber":113,"sourceCode":"\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}\n\n\tfor i, visitorData := range stored.Visitors {\n\t\tvisitorCfg, err := v1.DecodeVisitorConfigurerJSON(visitorData, v1.DecodeOptions{\n\t\t\tDisallowUnknownFields: false,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to decode visitor at index %d: %w\", i, err)\n\t\t}\n\t\tname := visitorCfg.GetBaseConfig().Name\n\t\tif name == \"\" {\n\t\t\treturn fmt.Errorf(\"visitor name cannot be empty\")\n\t\t}\n\t\ts.visitors[name] = visitorCfg\n\t}\n\n\treturn nil\n}\n\nfunc (s *StoreSource) saveToFileUnlocked() error {\n\tstored := storeData{\n\t\tProxies:  make([]v1.TypedProxyConfig, 0, len(s.proxies)),\n\t\tVisitors: make([]v1.TypedVisitorConfig, 0, len(s.visitors)),\n\t}\n\n\tfor _, p := range s.proxies {","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/source/store.go#L95-L131","documentation":"The visitor analogue of the proxy decode error: DecodeVisitorConfigurerJSON failed for the i-th element of the visitors array in the store file. Either the \"type\" discriminator does not match a registered VisitorConfigurer type (stcp, xtcp, sudp) or the payload is structurally incompatible with that type.","triggerScenarios":"A visitors entry with a misspelled/missing/unknown \"type\"; a store written by a newer frp containing visitor types the running build lacks; a payload field with the wrong JSON type for the target struct.","commonSituations":"Version downgrade after a newer frp wrote the store; hand-edited visitor entries; using a proxy type (e.g. \"tcp\") in the visitors array, which is not a visitor type.","solutions":["Check the visitors array element at the reported index in the store file","Confirm \"type\" is a valid visitor type for the running frp version (stcp, xtcp, sudp)","Upgrade frp if the entry was written by a newer release","Fix the type field or remove the broken entry and retry"],"exampleFix":"// before (visitors[0])\n{ \"type\": \"stcp\", \"name\": \"ssh-visitor\" }\n\n// after (if \"stcp\" unknown to this build, upgrade; or fix e.g. wrong array)\n{ \"type\": \"stcp\", \"name\": \"ssh-visitor\", \"serverName\": \"ssh\", \"secretKey\": \"...\" }","handlingStrategy":"validation","validationCode":"var supportedVisitorTypes = map[string]bool{\"stcp\": true, \"xtcp\": true, \"sudp\": true}\n\nfunc validateVisitorTypes(path string) error {\n\tdata, _ := os.ReadFile(path)\n\tvar raw struct {\n\t\tVisitors []json.RawMessage `json:\"visitors\"`\n\t}\n\tif json.Unmarshal(data, &raw) != nil {\n\t\treturn nil\n\t}\n\tfor i, v := range raw.Visitors {\n\t\tvar t struct{ Type string `json:\"type\"` }\n\t\tif json.Unmarshal(v, &t) != nil || !supportedVisitorTypes[t.Type] {\n\t\t\treturn fmt.Errorf(\"visitors[%d]: unsupported type %q\", i, t.Type)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not put proxy types (tcp/http/...) in the visitors array; only stcp/xtcp/sudp are visitors","Keep frp versions consistent across writers and readers of the store file","Validate machine-generated visitor entries with a schema check before deploy"],"tags":["json","schema","version-compat","config","decoding","visitor","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}