{"record":{"id":"c24eb47b375ded1e","repo":"MHSanaei/3x-ui","slug":"decode-inbound-list-w","errorCode":null,"errorMessage":"decode inbound list: %w","messagePattern":"decode inbound list: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/runtime/remote.go","lineNumber":377,"sourceCode":"\t\treturn nil, err\n\t}\n\tr.mu.RLock()\n\tdefer r.mu.RUnlock()\n\ttags := make([]string, 0, len(r.remoteIDByTag))\n\tfor tag := range r.remoteIDByTag {\n\t\ttags = append(tags, tag)\n\t}\n\treturn tags, nil\n}\n\nfunc (r *Remote) ListInboundOptions(ctx context.Context) ([]RemoteInboundOption, error) {\n\tenv, err := r.do(ctx, http.MethodGet, \"panel/api/inbounds/list\", nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar list []RemoteInboundOption\n\tif err := json.Unmarshal(env.Obj, &list); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode inbound list: %w\", err)\n\t}\n\treturn list, nil\n}\n\nfunc (r *Remote) refreshRemoteIDs(ctx context.Context) error {\n\tenv, err := r.do(ctx, http.MethodGet, \"panel/api/inbounds/list\", nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar list []struct {\n\t\tId  int    `json:\"id\"`\n\t\tTag string `json:\"tag\"`\n\t}\n\tif err := json.Unmarshal(env.Obj, &list); err != nil {\n\t\treturn fmt.Errorf(\"decode inbound list: %w\", err)\n\t}\n\tnext := make(map[string]int, len(list))\n\tfor _, ib := range list {","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/runtime/remote.go#L359-L395","documentation":"Returned by Remote.ListInboundOptions when the node's panel/api/inbounds/list succeeded at the HTTP/envelope level but env.Obj does not decode into []RemoteInboundOption. The node returned 200 with a success envelope whose obj payload has a different shape than the master expects — a wire-format mismatch between builds.","triggerScenarios":"Calling ListInboundOptions against a node running an older/newer release whose inbound list JSON differs (renamed fields, nulls where structs expected, obj being an object instead of an array); a node returning a success envelope with obj as a string error placeholder.","commonSituations":"Master upgraded but nodes left on the previous release (or vice versa); mixed-version chained topology; a fork/custom node build with modified API responses.","solutions":["Pin master and all nodes to the same release version; this is the most common cause and the fastest fix.","curl the node's /panel/api/inbounds/list and compare the obj shape with what the master's RemoteInboundOption expects.","Upgrade nodes one at a time and re-run the inbound-options fetch to confirm compatibility.","Report the field-level mismatch if both sides are on the latest release (regression)."],"exampleFix":"// before: master v3-new, node v3-old with different list shape\n// err: decode inbound list: json: cannot unmarshal object into Go struct field .obj of type []runtime.RemoteInboundOption\n\n// after: upgrade node to the same release -> list decodes","handlingStrategy":"validation","validationCode":"// Version-gate the feature before decoding\nif !nodeVersionAtLeast(n, minListOptionsVersion) {\n    return nil, fmt.Errorf(\"node %s too old for inbound options; upgrade it\", n.Name)\n}","typeGuard":"func isListDecodeError(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"decode inbound list:\")\n}","tryCatchPattern":"opts, err := remote.ListInboundOptions(ctx)\nif err != nil {\n    if isListDecodeError(err) {\n        return nil, fmt.Errorf(\"version mismatch with node %s: align releases and retry\", r.node.Name)\n    }\n    return nil, err\n}","preventionTips":["Treat master and node releases as one deployment unit — upgrade together.","Add a compatibility probe after node upgrades before enabling client-facing features.","Log the node's reported version with every decode failure to speed diagnosis."],"tags":["json","version-mismatch","node-sync","remote"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}