{"record":{"id":"a00d006d1bf356d8","repo":"fatedier/frp","slug":"line-d-field-s-cannot-unmarshal-s-into-s","errorCode":null,"errorMessage":"line %d: field \"%s\": cannot unmarshal %s into %s","messagePattern":"line (.+?): field \"(.+?)\": cannot unmarshal (.+?) into (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/load.go","lineNumber":240,"sourceCode":"\tif errors.As(err, &decErr) {\n\t\trow, col := decErr.Position()\n\t\treturn fmt.Errorf(\"toml: line %d, column %d: %s\", row, col, decErr.Error())\n\t}\n\tvar strictErr *toml.StrictMissingError\n\tif errors.As(err, &strictErr) {\n\t\treturn strictErr\n\t}\n\treturn err\n}\n\n// enhanceDecodeError tries to add field path and line number information to JSON/YAML decode errors.\nfunc enhanceDecodeError(err error, originalContent []byte, includeLine bool) error {\n\tvar typeErr *json.UnmarshalTypeError\n\tif errors.As(err, &typeErr) && typeErr.Field != \"\" {\n\t\tif includeLine {\n\t\t\tline := findFieldLineInContent(originalContent, typeErr.Field)\n\t\t\tif line > 0 {\n\t\t\t\treturn fmt.Errorf(\"line %d: field \\\"%s\\\": cannot unmarshal %s into %s\", line, typeErr.Field, typeErr.Value, typeErr.Type)\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"field \\\"%s\\\": cannot unmarshal %s into %s\", typeErr.Field, typeErr.Value, typeErr.Type)\n\t}\n\treturn err\n}\n\n// findFieldLineInContent searches the original config content for a field name\n// and returns the 1-indexed line number where it appears, or 0 if not found.\nfunc findFieldLineInContent(content []byte, fieldPath string) int {\n\tif fieldPath == \"\" {\n\t\treturn 0\n\t}\n\n\t// Use the last component of the field path (e.g. \"proxies\" from \"proxies\" or\n\t// \"protocol\" from \"transport.protocol\").\n\tparts := strings.Split(fieldPath, \".\")\n\tsearchKey := parts[len(parts)-1]","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/load.go#L222-L258","documentation":"enhanceDecodeError upgrades encoding/json UnmarshalTypeError for JSON/YAML frp configs into a message with the 1-indexed line where the field appears (findFieldLineInContent scans the raw file), the field path, the value Go saw, and the target type. It fires when a field decodes to a value of the wrong Go type, e.g. a string given where an int is required.","triggerScenarios":"A YAML/TOML/JSON client or server config where e.g. transport.heartbeatInterval is set to \"30\" (string) instead of 30, or a list is given for a scalar field; includeLine is true for file-based loads so the line is resolved from the original bytes.","commonSituations":"Quoting numbers in YAML; pasting values from web UIs that stringify everything; struct changes across frp versions altering a field's expected type.","solutions":["Go to the reported line and change the value to the type shown in the message (e.g. remove quotes around integers)","Check the frp schema/docs for the field's expected type","Re-run frpc verify until decoding succeeds"],"exampleFix":"# before (line 8: field \"heartbeatInterval\": cannot unmarshal string into int64)\ntransport.heartbeatInterval = \"30\"\n\n# after\ntransport.heartbeatInterval = 30","handlingStrategy":"validation","validationCode":"// schema-check JSON content before load\nvar generic map[string]any\nif err := json.Unmarshal(raw, &generic); err == nil { _ = checkTypesAgainstSchema(generic, schema) } // custom walker comparing kinds","typeGuard":null,"tryCatchPattern":"if err := config.LoadConfigureFromFile(path, &cfg, strict); err != nil { var te *json.UnmarshalTypeError; if errors.As(err, &te) { /* te.Field, te.Value, te.Type available for targeted message */ } }","preventionTips":["Never quote numeric config values","Use frp's JSON schema in the editor","Verify generated configs with frpc verify"],"tags":["config","yaml","json","type-conversion","parsing"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}