{"record":{"id":"941d2a1b5752723a","repo":"apache/beam","slug":"error-evaluating-javascript-expression-exn","errorCode":null,"errorMessage":"Error evaluating javascript expression: {exn}","messagePattern":"Error evaluating javascript expression: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/yaml_mapping.py","lineNumber":227,"sourceCode":"        try:\n          result = f(*[convert_arg(a) for a in args])\n          if isinstance(result, quickjs.Object):\n            result = json.loads(result.json())\n          return result\n        finally:\n          if run_gc:\n            context.gc()\n\n      cache.functions[cache_key] = call_fn\n\n    return cache.functions[cache_key]\n\n  def __call__(self, row):\n    fn = self._get_fn()\n    try:\n      return dicts_to_rows(fn(py_value_to_js_dict(row)))\n    except Exception as exn:\n      raise RuntimeError(\n          f\"Error evaluating javascript expression: {exn}\") from exn\n\n\n# TODO(yaml) Improve type inferencing for JS UDF's\ndef py_value_to_js_dict(py_value):\n  if ((isinstance(py_value, tuple) and hasattr(py_value, '_asdict')) or\n      isinstance(py_value, beam.Row)):\n    py_value = py_value._asdict()\n  if isinstance(py_value, dict):\n    return {key: py_value_to_js_dict(value) for key, value in py_value.items()}\n  elif isinstance(py_value, bytes):\n    return py_value.decode('utf-8', errors='replace')\n  elif isinstance(py_value, (datetime.datetime, datetime.date, datetime.time)):\n    return {'__date__': True, 'value': py_value.isoformat()}\n  elif isinstance(py_value, Decimal):\n    return float(py_value)\n  elif not isinstance(py_value, str) and isinstance(py_value, abc.Iterable):\n    return [py_value_to_js_dict(value) for value in list(py_value)]","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/yaml_mapping.py#L209-L245","documentation":"_JsFunctionWrapper.__call__ evaluates a JavaScript UDF via quickjs for each row. If the JS function raises or the row conversion fails, the exception is wrapped in a RuntimeError with the original exception chained ('Error evaluating javascript expression: {exn}').","triggerScenarios":"The JS expression/function throws at runtime for a given row — e.g. undefined property access, type coercion errors, returning a shape that doesn't match the expected output schema during dicts_to_rows conversion.","commonSituations":"Null/undefined handling mistakes in JS; field-name mismatches between the schema and the JS code; JS strict-mode type errors on unexpected input data.","solutions":["Read the chained exception (exn) to find the JS-level error and line.","Test the JS expression in a JS runtime/quickjs with a representative row.","Add guards in JS for null/undefined fields before use.","Verify output field names/types match the declared output schema."],"exampleFix":"// before\nfunction udf(row) {\n  return {out: row.value + 1};  // throws if value undefined\n}\n// after\nfunction udf(row) {\n  return {out: (row.value == null ? 0 : Number(row.value)) + 1};\n}","handlingStrategy":"try-catch","validationCode":"new Function('row', js_body)({/* sample row */})  // dry-run the JS on a sample row","typeGuard":null,"tryCatchPattern":"try:\n    result = map_row(row)\nexcept RuntimeError as e:\n    logger.error('JS UDF failed for row %r: %s', row, e.__cause__)\n    raise","preventionTips":["Dry-run the JS expression on sample rows before running the pipeline","Guard null/undefined fields in JS","Keep JS output field names/types aligned with the declared schema"],"tags":["javascript","beam-yaml","runtime"],"backgroundTag":"api-error-response","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"}