{"record":{"id":"716273d6b9a42180","repo":"ComposioHQ/composio","slug":"refusing-to-build-a-path-from-a-label-longer-tha","errorCode":null,"errorMessage":"Refusing to build a path from a {label} longer than {MAX_COMPONENT_LENGTH} characters: {value[:32]!r}... ({len(value)} characters)","messagePattern":"Refusing to build a path from a (.+?) longer than (.+?) characters: (.+?)\\.\\.\\. \\((.+?) characters\\)","errorType":"validation","errorClass":"UnsafePathComponentError","httpStatus":null,"severity":"error","filePath":"python/composio/utils/safe_path.py","lineNumber":116,"sourceCode":"    :raises UnsafePathComponentError: when ``value`` is unsafe.\n    \"\"\"\n    if not isinstance(value, str) or not value:\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from an empty or non-string {label}: {value!r}\"\n        )\n\n    # `PureWindowsPath` treats both `/` and `\\` as separators, so a single check\n    # catches `../x` and `..\\x` regardless of the host platform. A slug crafted\n    # for a Windows target must not slip through on a POSIX build machine.\n    as_windows_path = PureWindowsPath(value)\n    if len(as_windows_path.parts) != 1 or as_windows_path.anchor:\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from a {label} containing path separators \"\n            f\"or a drive letter: {value!r}\"\n        )\n\n    if len(value) > MAX_COMPONENT_LENGTH:\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from a {label} longer than \"\n            f\"{MAX_COMPONENT_LENGTH} characters: {value[:32]!r}... \"\n            f\"({len(value)} characters)\"\n        )\n\n    # `.` and `..` are excluded by the regex (no `.` in the character class),\n    # as are NUL bytes and every separator. The explicit checks above exist to\n    # produce a precise error message rather than a generic pattern mismatch.\n    #\n    # `fullmatch`, not `match`: in a `match`, `$` also matches just before a\n    # single trailing newline, so `\"GMAIL\\n\"` would satisfy `^[A-Za-z0-9_-]+$`\n    # and reach the filesystem with a control character in the name.\n    if not SAFE_COMPONENT_REGEX.fullmatch(value):\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from an unsafe {label}: {value!r}. \"\n            f\"Expected only letters, digits, underscores, and hyphens \"\n            f\"(pattern {SAFE_COMPONENT_REGEX.pattern}).\"\n        )","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/utils/safe_path.py#L98-L134","documentation":"assert_safe_path_component rejects a single path component longer than MAX_COMPONENT_LENGTH (128 characters), keeping components well under the 255-byte filename limit of ext4/APFS/NTFS so a write never fails mid-operation with OSError.","triggerScenarios":"secure_join(root, slug) where slug exceeds 128 chars — e.g. a generated ID, hash, or long tool/action name used as a directory name.","commonSituations":"Backend-generated composite IDs or namespaced slugs (tool__action__param hashes) used directly as cache/workspace directory names.","solutions":["Hash or truncate long identifiers before using them as directory names (e.g. sha256 hex of the slug)","Store the full identifier in a metadata file inside a short-named directory","Report legitimate catalog slugs that exceed 128 chars"],"exampleFix":"# before\nsecure_join(root, very_long_slug)\n# after\nimport hashlib\nshort = hashlib.sha256(very_long_slug.encode()).hexdigest()[:32]\nsecure_join(root, short)","handlingStrategy":"validation","validationCode":"def component_within_limit(v):\n    return isinstance(v, str) and 0 < len(v) <= 128","typeGuard":"def is_short_component(v) -> bool:\n    return isinstance(v, str) and 0 < len(v) <= 128","tryCatchPattern":"from composio.exceptions import UnsafePathComponentError\nimport hashlib\ntry:\n    p = secure_join(root, slug)\nexcept UnsafePathComponentError:\n    p = secure_join(root, hashlib.sha256(slug.encode()).hexdigest()[:32])","preventionTips":["Hash long identifiers before using them as directory names","Keep generated slug length bounded at creation time"],"tags":["path-length","validation","python"],"backgroundTag":"filename-too-long","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}