{"record":{"id":"f01891ddd8e77177","repo":"wavetermdev/waveterm","slug":"invalid-path-part-pathpart","errorCode":null,"errorMessage":"Invalid path part: ${pathPart}","messagePattern":"Invalid path part: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/util/ijson.ts","lineNumber":59,"sourceCode":"    let cur = obj;\n    for (const pathPart of path) {\n        if (cur == null) {\n            return null;\n        }\n        if (typeof pathPart === \"string\") {\n            if (isObject(cur)) {\n                cur = cur[pathPart];\n            } else {\n                return null;\n            }\n        } else if (typeof pathPart === \"number\") {\n            if (isArray(cur)) {\n                cur = cur[pathPart];\n            } else {\n                return null;\n            }\n        } else {\n            throw new Error(\"Invalid path part: \" + pathPart);\n        }\n    }\n    return cur;\n}\n\ntype SetPathOpts = {\n    force?: boolean;\n    remove?: boolean;\n    combinefn?: (oldVal: any, newVal: any, opts: SetPathOpts) => any;\n};\n\nfunction combineFn_arrayAppend(oldVal: any, newVal: any, opts: SetPathOpts): any {\n    if (oldVal == null) {\n        return [newVal];\n    }\n    if (!isArray(oldVal) && !opts.force) {\n        throw new Error(\"Cannot append to non-array: \" + oldVal);\n    }","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/frontend/util/ijson.ts#L41-L77","documentation":"getPath walks an ijson object along a path array of keys/indices. When a segment is a string (object key) but the current node is neither an object nor an array-compatible structure — i.e. the key type doesn't match the node type — it throws \"Invalid path part\". Note the visible branch throws when the segment is otherwise unusable on the current value.","triggerScenarios":"Calling getPath(obj, path) where a string pathPart is applied to a node that is not an object (e.g. traversing into a primitive, null, or a string key on a non-container).","commonSituations":"Assuming a nested field exists when an intermediate value is a primitive; schema drift between the expected atom/JSON shape and actual data; passing a path built for one object shape to another.","solutions":["Verify the object's actual shape at each path segment before deep traversal","Use optional access (getPath already returns null for array mismatch) or guard segments against the node type","Fix the path construction so keys match the real nesting of the ijson atom"],"exampleFix":"// before\ngetPath(atom, [\"meta\", \"sub\", \"key\"]);\n\n// after\nconst mid = getPath(atom, [\"meta\"]);\nconst val = mid && typeof mid === \"object\" ? getPath(atom, [\"meta\", \"sub\", \"key\"]) : null;","handlingStrategy":"validation","validationCode":"const cur = getPath(obj, [\"meta\"]);\nif (cur == null || typeof cur !== \"object\") return null; // don't traverse further","typeGuard":"function isTraversable(v: unknown): v is Record<string, unknown> {\n    return v != null && typeof v === \"object\";\n}","tryCatchPattern":"let value;\ntry {\n    value = getPath(atom, path);\n} catch (e) {\n    if (String(e.message).startsWith(\"Invalid path part\")) {\n        value = null; // treat as missing\n    } else { throw e; }\n}","preventionTips":["Build paths from the actual observed shape of the atom, not assumed schemas","Check intermediate values before deep path traversal","Prefer returning null for missing branches and reserve throwing for true type mismatches"],"tags":["ijson","path-traversal","type-mismatch"],"backgroundTag":"invalid-path-segment","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}