{"record":{"id":"cc76de80225d5fee","repo":"MHSanaei/3x-ui","slug":"decode-web-cert-files-w","errorCode":null,"errorMessage":"decode web cert files: %w","messagePattern":"decode web cert files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/runtime/remote.go","lineNumber":648,"sourceCode":"\n// WebCertFiles holds a node's own web TLS certificate and key file paths.\ntype WebCertFiles struct {\n\tWebCertFile string `json:\"webCertFile\"`\n\tWebKeyFile  string `json:\"webKeyFile\"`\n}\n\n// GetWebCertFiles fetches the node's own web TLS certificate/key file paths so\n// the central panel can offer them as the \"Set Cert from Panel\" default for a\n// node-assigned inbound — those paths exist on the node, the central panel's\n// don't. See issue #4854.\nfunc (r *Remote) GetWebCertFiles(ctx context.Context) (*WebCertFiles, error) {\n\tenv, err := r.do(ctx, http.MethodGet, \"panel/api/server/getWebCertFiles\", nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar files WebCertFiles\n\tif err := json.Unmarshal(env.Obj, &files); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode web cert files: %w\", err)\n\t}\n\treturn &files, nil\n}\n\n// GetDescendants fetches the node's read-only summaries of the nodes IT\n// manages, so this panel can surface them as transitive sub-nodes in a chained\n// topology (#4983). Best-effort: an old-build node without the endpoint returns\n// an error the caller ignores.\nfunc (r *Remote) GetDescendants(ctx context.Context) ([]model.NodeSummary, error) {\n\tenv, err := r.do(ctx, http.MethodGet, \"panel/api/server/descendants\", nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar out []model.NodeSummary\n\tif len(env.Obj) > 0 {\n\t\tif err := json.Unmarshal(env.Obj, &out); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decode descendants: %w\", err)\n\t\t}","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/runtime/remote.go#L630-L666","documentation":"Returned by Remote.GetWebCertFiles when the node's panel/api/server/getWebCertFiles endpoint answered 200 but env.Obj does not decode into WebCertFiles (the expected cert/key path strings). The node-side handler exists (otherwise error 101/102 would fire), but the payload shape does not match.","triggerScenarios":"Invoking 'Set Cert from Panel' for a node-assigned inbound against a node build whose getWebCertFiles returns a different obj shape, obj:null, or an error object inside a success envelope; node version predates the field layout the master expects.","commonSituations":"Master newer than node (endpoint added recently, layout drifted); node where web cert paths are unset so the handler returns obj with nulls on older builds.","solutions":["Upgrade the node to the same release as the master — this endpoint is version-coupled (issue #4854 feature).","curl the endpoint on the node and compare obj's keys with WebCertFiles fields.","If the node has no cert configured, set the node's own web cert first so the handler returns real paths.","As a workaround, enter the cert paths manually instead of using the panel-default fetch."],"exampleFix":"// before: old node returns {\"obj\": null} when no cert is set\n// err: decode web cert files: json: cannot unmarshal null into Go value of type runtime.WebCertFiles\n\n// after: upgrade node / configure the node's web cert so obj carries the path strings","handlingStrategy":"fallback","validationCode":"// Version/feature gate before offering the panel-default cert button\nif !nodeSupportsWebCertFiles(n) {\n    ui.DisableSetCertFromPanel(n.ID) // fall back to manual path entry\n}","typeGuard":"func isCertDecodeError(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"decode web cert files:\")\n}","tryCatchPattern":"files, err := nodeSvc.GetWebCertFiles(id)\nif err != nil {\n    if isCertDecodeError(err) {\n        files = nil // degrade to manual cert path input in the UI\n    } else {\n        return err\n    }\n}","preventionTips":["Upgrade nodes before using cert-from-panel on them (feature is version-coupled, #4854).","Configure the node's own web cert first so the endpoint returns real paths.","Keep a manual cert-path fallback in workflows that span mixed versions."],"tags":["json","tls","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"}