{"record":{"id":"4b9e40805fe18f09","repo":"larksuite/cli","slug":"secretref-id-must-be-non-empty","errorCode":null,"errorMessage":"SecretRef.id must be non-empty","messagePattern":"SecretRef\\.id must be non-empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/binding/types.go","lineNumber":107,"sourceCode":"\n// UnmarshalJSON handles both string and object forms of SecretInput.\nfunc (s *SecretInput) UnmarshalJSON(data []byte) error {\n\t// Try string first\n\tvar str string\n\tif err := json.Unmarshal(data, &str); err == nil {\n\t\ts.Plain = str\n\t\ts.Ref = nil\n\t\treturn nil\n\t}\n\n\t// Try SecretRef object\n\tvar ref SecretRef\n\tif err := json.Unmarshal(data, &ref); err == nil {\n\t\tif !validSources[ref.Source] {\n\t\t\treturn fmt.Errorf(\"SecretRef.source must be env|file|exec, got %q\", ref.Source)\n\t\t}\n\t\tif ref.ID == \"\" {\n\t\t\treturn fmt.Errorf(\"SecretRef.id must be non-empty\")\n\t\t}\n\t\ts.Ref = &ref\n\t\ts.Plain = \"\"\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"appSecret must be a string or {source, provider?, id} object\")\n}\n\n// MarshalJSON serializes SecretInput back to JSON.\nfunc (s SecretInput) MarshalJSON() ([]byte, error) {\n\tif s.Ref != nil {\n\t\treturn json.Marshal(s.Ref)\n\t}\n\treturn json.Marshal(s.Plain)\n}\n\n// SecretsConfig captures the secrets.providers registry from openclaw.json.","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/binding/types.go#L89-L125","documentation":"SecretInput.UnmarshalJSON requires SecretRef.id to be a non-empty string. The id identifies which secret the provider should fetch; an empty id is unresolvable, so unmarshal fails fast instead of producing a ref that errors at lookup.","triggerScenarios":"Parsing a SecretRef object with an empty or missing id, e.g. {\"source\":\"env\"} or {\"source\":\"env\",\"id\":\"\"}.","commonSituations":"Template-expanded config where a placeholder variable was empty; deleting the id value during refactoring; copy-paste dropping the id field.","solutions":["Set id to the secret name/key the provider should resolve","If the value is meant to be literal plaintext, pass a plain string instead of a ref object","Check that the env var or config template supplying the id expands to a non-empty value"],"exampleFix":"// before\n{\"appSecret\": {\"source\": \"env\", \"id\": \"\"}}\n// after\n{\"appSecret\": {\"source\": \"env\", \"id\": \"FEISHU_APP_SECRET\"}}","handlingStrategy":"validation","validationCode":"if ref.ID == \"\" {\n    return errors.New(\"secretRef.id must be non-empty\")\n}","typeGuard":"func hasSecretID(m map[string]any) bool {\n    id, ok := m[\"id\"].(string)\n    return ok && id != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never template-expand refs without asserting non-empty interpolation","Validate refs at config-load time, before any provider call","Prefer explicit strings over omitted fields so missing ids are visible in diffs"],"tags":["config","json","validation","secrets"],"backgroundTag":"missing-required-argument","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}