{"record":{"id":"30fb0ea9a4c2204f","repo":"pentaho/pentaho-kettle","slug":"invalid-path-id","errorCode":null,"errorMessage":"Invalid path: '${id}'.","messagePattern":"Invalid path: '(.+?)'\\.","errorType":"exception","errorClass":"pentaho.lang.OperationInvalidError","httpStatus":null,"severity":"error","filePath":"plugins/core-ui/src/main/resources/app/pentaho/module/util.js","lineNumber":89,"sourceCode":"\n    absolutizeIdRelativeToSibling: function(id, siblingId) {\n      return this.absolutizeId(id, this.getBaseIdOf(siblingId));\n    },\n\n    absolutizeId: function(id, baseId) {\n      if(id && /^\\./.test(id) && !/\\.js$/.test(id)) {\n        var baseIds = baseId ? baseId.split(\"/\") : [];\n        var ids = id.split(\"/\");\n        var needsBase = false;\n\n        while(ids.length) {\n          var segment = ids[0];\n          if(segment === \".\") {\n            ids.shift();\n            needsBase = true;\n          } else if(segment === \"..\") {\n            if(!baseIds.pop()) {\n              throw new OperationInvalidError(\"Invalid path: '\" + id + \"'.\");\n            }\n            ids.shift();\n            needsBase = true;\n          } else {\n            break;\n          }\n        }\n\n        if(needsBase) {\n          baseId = baseIds.join(\"/\");\n          id = ids.join(\"/\");\n\n          return (baseId && id) ? (baseId + \"/\" + id) : (baseId || id);\n        }\n      }\n\n      return id;\n    },","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/core-ui/src/main/resources/app/pentaho/module/util.js#L71-L107","documentation":"The module id resolution utility (util.js resolveIdRelative) normalizes relative ids ('.' and '..' segments) against a base id. When a '..' segment tries to go above the root of the base id (baseIds.pop() returns undefined), the path cannot be resolved and OperationInvalidError is thrown.","triggerScenarios":"Resolving an id like '../../some/module' against a base id with too few path segments, e.g. base 'pkg/module' with '../..' — popping the last segment leaves nothing to pop.","commonSituations":"Hand-written relative AMD/requirejs module ids with excess '../' segments; config or plugin descriptors referencing modules relative to the wrong base; typos after refactoring module paths.","solutions":["Fix the relative id so '..' segments do not exceed the base path depth.","Use an absolute module id (e.g. 'my/package/sub/module') instead of a deep relative path.","Validate the resolved path depth against the base before calling the resolver."],"exampleFix":"// before\nresolveIdRelative('../../foo', 'pkg/mod'); // throws\n// after\nresolveIdRelative('./foo', 'pkg/sub/mod');\n// or use absolute id\nresolveIdRelative('pkg/sub/foo');","handlingStrategy":"validation","validationCode":"var ups = (id.match(/\\.\\.\\//g) || []).length;\nvar depth = baseId ? baseId.split('/').length : 0;\nif (ups >= depth) throw new Error('Relative id escapes base: ' + id);","typeGuard":"function isResolvableRelativeId(id, baseId) { return typeof id === 'string' && (id.charAt(0) !== '.' || (baseId && (baseId.split('/').length > (id.match(/\\.\\.\\//g) || []).length))); }","tryCatchPattern":"try { resolved = util.resolveId(id, baseId); } catch (e) { if (/Invalid path/.test(e.message)) { resolved = defaultModuleId; } else throw e; }","preventionTips":["Count '../' segments against the base path depth before resolving.","Prefer absolute module ids in config and plugin descriptors.","Avoid hand-building relative ids with string concatenation."],"tags":["module-id","path-resolution","invalid-path"],"backgroundTag":"invalid-identifier-format","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}