{"record":{"id":"83c66e32584ba7e1","repo":"apache/beam","slug":"index-index-is-out-of-bounds-for-obj-defaults-len-obj","errorCode":null,"errorMessage":"Index {index} is out of bounds for obj.__defaults__ {len(obj.__defaults__)} in path {code_object_identifier}","messagePattern":"Index (.+?) is out of bounds for obj\\.__defaults__ (.+?) in path (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/internal/code_object_pickler.py","lineNumber":454,"sourceCode":"    raise ValueError('Path must not be empty.')\n  parts = code_object_identifier.split('.')\n  if parts[0] not in sys.modules:\n    raise AttributeError(f'Module {parts[0]} not found in sys.modules')\n  obj = sys.modules[parts[0]]\n  for part in parts[1:]:\n    if name_result := _SINGLE_NAME_PATTERN.fullmatch(part):\n      obj = _get_code_object_from_single_name_pattern(\n          obj, name_result, code_object_identifier)\n    elif lambda_with_args_result := _LAMBDA_WITH_ARGS_PATTERN.fullmatch(part):\n      obj = _get_code_object_from_lambda_with_args_pattern(\n          obj, lambda_with_args_result, code_object_identifier)\n    elif lambda_with_hash_result := _LAMBDA_WITH_HASH_PATTERN.fullmatch(part):\n      obj = _get_code_object_from_lambda_with_hash_pattern(\n          obj, lambda_with_hash_result, code_object_identifier)\n    elif default_result := _DEFAULT_PATTERN.fullmatch(part):\n      index = int(default_result.group(2))\n      if index >= len(obj.__defaults__):\n        raise ValueError(\n            f'Index {index} is out of bounds for obj.__defaults__'\n            f' {len(obj.__defaults__)} in path {code_object_identifier}')\n      obj = getattr(obj, '__defaults__')[index]\n    else:\n      obj = getattr(obj, part)\n  if isinstance(obj, types.CodeType):\n    return obj\n  else:\n    raise AttributeError(\n        f'Could not find code object with path: {code_object_identifier}')\n\n\ndef _signature(obj: types.CodeType):\n  \"\"\"Returns the signature of a code object.\n\n  The signature is the names of the arguments of the code object. This is used\n  to unique identify lambdas.\n","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/internal/code_object_pickler.py#L436-L472","documentation":"When resolving a path segment matching the default-argument pattern, Beam indexes obj.__defaults__ with the parsed integer. If the index equals or exceeds the number of default values on the function/code object, ValueError is raised naming the index, its length, and the full path. The serialized default reference points at a slot that does not exist.","triggerScenarios":"get_code_from_identifier('module.func.__defaults__[2]') where func has fewer than 3 default arguments; identifier generated when func had more defaults, then the function signature changed; off-by-one in code constructing the path.","commonSituations":"Signature refactoring between identifier creation and resolution; hand-written test paths indexing defaults incorrectly; stale pickled references after editing defaults.","solutions":["Verify len(func.__defaults__) covers the index: `assert i < len(f.__defaults__)` before calling.","Regenerate the identifier after any change to the function's default arguments.","Fix the index in the path (0-based) if it was constructed incorrectly.","Replace default-value serialization with passing the value explicitly through the pipeline."],"exampleFix":"// before\ni = 2\nget_code_from_identifier(f'mylib.f.__defaults__[{i}]')  # f has 1 default\n// after\ni = 0\nassert i < len(mylib.f.__defaults__)\nget_code_from_identifier(f'mylib.f.__defaults__[{i}]')","handlingStrategy":"validation","validationCode":"import sys\ndef defaults_index_ok(path):\n    head, _, seg = path.rpartition('.')\n    if '__defaults__' not in seg or '[' not in seg: return True\n    i = int(seg[seg.index('[')+1:-1])\n    mod_name, _, rest = head.partition('.')\n    obj = sys.modules[mod_name]\n    for p in rest.split('.'): obj = getattr(obj, p)\n    return i < len(getattr(obj, '__defaults__', ()))","typeGuard":"def is_safe_defaults_index(fn, i) -> bool:\n    return 0 <= i < len(getattr(fn, '__defaults__', ()))","tryCatchPattern":"try:\n    code = get_code_from_identifier(path)\nexcept ValueError as e:\n    raise RuntimeError(f'Default-index in {path} exceeds current signature; regenerate identifier') from e","preventionTips":["Regenerate identifiers after changing function signatures/default arguments.","Compute indices from len(f.__defaults__) rather than hardcoding.","Add a unit test resolving serialized identifiers against current source."],"tags":["python","apache-beam","pickling","index-out-of-range"],"backgroundTag":"index-out-of-bounds","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}