{"record":{"id":"efa694a1f4213ad2","repo":"larksuite/cli","slug":"json-pointer-must-start-with-or-be-empty-got","errorCode":null,"errorMessage":"json pointer must start with '/' or be empty, got %q","messagePattern":"json pointer must start with '/' or be empty, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/binding/json_pointer.go","lineNumber":27,"sourceCode":")\n\n// ReadJSONPointer navigates a parsed JSON value (typically the result of\n// json.Unmarshal into interface{}) using an RFC 6901 JSON Pointer string.\n//\n// Supported pointer format: \"/key/subkey/subsubkey\".\n// An empty pointer (\"\") returns data as-is.\n// RFC 6901 escape sequences: ~1 → /, ~0 → ~.\n//\n// Limitation: only object (map) traversal is supported. Array index segments\n// (e.g., \"/channels/0/appId\") are not implemented because OpenClaw's\n// SecretRef file provider uses object-only paths in practice.\nfunc ReadJSONPointer(data interface{}, pointer string) (interface{}, error) {\n\tif pointer == \"\" {\n\t\treturn data, nil\n\t}\n\n\tif !strings.HasPrefix(pointer, \"/\") {\n\t\treturn nil, fmt.Errorf(\"json pointer must start with '/' or be empty, got %q\", pointer)\n\t}\n\n\t// Split after the leading \"/\" and decode each segment.\n\tsegments := strings.Split(pointer[1:], \"/\")\n\tcurrent := data\n\n\tfor i, raw := range segments {\n\t\t// RFC 6901 unescaping: ~1 → /, ~0 → ~ (order matters).\n\t\tkey, err := decodeJSONPointerSegment(raw)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"json pointer %q: segment %q: %w\", pointer, raw, err)\n\t\t}\n\n\t\tm, ok := current.(map[string]interface{})\n\t\tif !ok {\n\t\t\ttraversed := \"/\" + strings.Join(segments[:i], \"/\")\n\t\t\treturn nil, fmt.Errorf(\"json pointer %q: value at %q is %T, not an object\",\n\t\t\t\tpointer, traversed, current)","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/binding/json_pointer.go#L9-L45","documentation":"ReadJSONPointer implements RFC 6901 JSON Pointer traversal over a parsed JSON value. Per the spec, a pointer must be either the empty string (returns the whole document) or start with '/'. This error rejects any non-empty pointer lacking the leading slash before any traversal happens.","triggerScenarios":"Calling ReadJSONPointer(data, \"key\") or \"a.b\" — any pointer that is neither \"\" nor starts with '/'.","commonSituations":"Users writing dot-notation (\"accounts.app.id\") or bare key names in a SecretRef path; config values copied from JSONPath; whitespace before the slash.","solutions":["Prefix the pointer with '/': \"accounts/app/id\" not \"accounts.app.id\"","Use the empty string \"\" when you want the entire document","Trim whitespace and convert dot-separated paths to slash-separated segments"],"exampleFix":"// before\nReadJSONPointer(data, \"accounts.app.id\")\n// after\nReadJSONPointer(data, \"/accounts/app/id\")","handlingStrategy":"validation","validationCode":"func validPointer(p string) bool { return p == \"\" || strings.HasPrefix(p, \"/\") }\nif !validPointer(ptr) {\n    ptr = \"/\" + strings.ReplaceAll(strings.TrimLeft(ptr, \".\"), \".\", \"/\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write JSON Pointers in RFC 6901 form with a leading '/'","Convert dot-notation paths to slash-separated form at config-load time","Trim whitespace before passing the pointer"],"tags":["json","rfc6901","validation"],"backgroundTag":"invalid-json-pointer","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"}