{"record":{"id":"f51908436393001c","repo":"apache/beam","slug":"s-s-row-r","errorCode":null,"errorMessage":"%s. %s. Row: %r","messagePattern":"(.+?)\\. (.+?)\\. Row: %r","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/gcp/bigquery_tools.py","lineNumber":1449,"sourceCode":"class RowAsDictJsonCoder(coders.Coder):\n  \"\"\"A coder for a table row (represented as a dict) to/from a JSON string.\n\n  This is the default coder for sources and sinks if the coder argument is not\n  specified.\n  \"\"\"\n  def encode(self, table_row):\n    # The normal error when dumping NAN/INF values is:\n    # ValueError: Out of range float values are not JSON compliant\n    # This code will catch this error to emit an error that explains\n    # to the programmer that they have used NAN/INF values.\n    try:\n      return json.dumps(\n          table_row,\n          allow_nan=False,\n          ensure_ascii=False,\n          default=default_encoder).encode('utf-8')\n    except ValueError as e:\n      raise ValueError(\n          '%s. %s. Row: %r' % (e, JSON_COMPLIANCE_ERROR, table_row))\n\n  def decode(self, encoded_table_row):\n    return json.loads(encoded_table_row.decode('utf-8'))\n\n  def to_type_hint(self):\n    return Any\n\n\nclass JsonRowWriter(io.IOBase):\n  \"\"\"\n  A writer which provides an IOBase-like interface for writing table rows\n  (represented as dicts) as newline-delimited JSON strings.\n  \"\"\"\n  def __init__(self, file_handle):\n    \"\"\"Initialize an JsonRowWriter.\n\n    Args:","sourceCodeStart":1431,"sourceCodeEnd":1467,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/gcp/bigquery_tools.py#L1431-L1467","documentation":"Raised by `JsonCoder.encode` (RowAsDictJsonCoder) when json.dumps fails — typically because the row dict contains NaN or Infinity (allow_nan=False) — wrapping the original ValueError with the JSON_COMPLIANCE_ERROR explanation and the offending row. BigQuery streaming rows must be valid JSON, and NaN/Infinity literals are not JSON-compliant.","triggerScenarios":"Encoding a row dict containing float('nan'), float('inf'), or -inf (common from 0/0, numpy operations, or missing-value placeholders) when writing to BigQuery with the file_loads or streaming-insert JSON path.","commonSituations":"Pipelines over numpy/pandas data where NaN is a default missing marker; computed metrics dividing by zero; ML feature pipelines emitting inf from log/exp transforms; upstream CSV loads using NaN placeholders.","solutions":["Sanitize the row before writing: replace NaN/inf with None (NULL column) or a sentinel numeric value.","Use math.isnan/math.isinf checks in a map step before the BigQuery sink.","In pandas/numpy sources, apply df.replace([np.inf, -np.inf], np.nan).where(df.notna(), None).","Fix the computation producing NaN/inf (guard divisions, clip log/exp inputs)."],"exampleFix":"// before\nrows | beam.io.WriteToBigQuery(table, method=beam.io.WriteToBigQuery.Method.FILE_LOADS)\n// after\ndef clean(row):\n    return {k: (None if isinstance(v, float) and (math.isnan(v) or math.isinf(v)) else v) for k, v in row.items()}\nrows | beam.Map(clean) | beam.io.WriteToBigQuery(table, method=beam.io.WriteToBigQuery.Method.FILE_LOADS)","handlingStrategy":"validation","validationCode":"import math\ndef json_safe_row(row):\n    return {k: (None if isinstance(v, float) and (math.isnan(v) or math.isinf(v)) else v)\n            for k, v in row.items()}\n# map rows through this before the BigQuery sink","typeGuard":"def is_json_compliant_value(v):\n    return not (isinstance(v, float) and (math.isnan(v) or math.isinf(v)))","tryCatchPattern":"try:\n    encoded = coder.encode(row)\nexcept ValueError as e:\n    if 'JSON_COMPLIANCE' in str(e) or 'Out of range' in str(e) or 'NaN' in str(e):\n        row = sanitize_row(row)\n        encoded = coder.encode(row)\n    else:\n        raise","preventionTips":["Replace NaN/inf with None at the point where floats are produced.","Guard divisions and log/exp transforms that can generate inf.","For pandas sources use df.replace([np.inf,-np.inf], np.nan).where(df.notna(), None)."],"tags":["bigquery","python","json","serialization"],"backgroundTag":"json-serialization-failed","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"}