Docs /Querying /SAFE functions
Querying

SAFE_CAST, SAFE_DIVIDE and the SAFE. prefix in BigQuery

One bad value stops a whole BigQuery query. SAFE_CAST, SAFE_DIVIDE, the SAFE_ math functions and the SAFE. prefix return NULL instead of failing, and how to find the rows that would have failed.

When one row out of a billion holds a value a function can’t handle, BigQuery fails the whole query. There is no partial result and no list of bad rows, only the error message. The SAFE family turns those errors into NULL: SAFE_CAST for casts, SAFE_DIVIDE and the other SAFE_ math functions for arithmetic, and the SAFE. prefix for almost every other function.

One bad value fails the query

A text column that should hold numbers, with one 'n/a' in it:

CAST on a column with one bad valueBigQuery rejects this query
1234567
WITH raw AS (
  SELECT '42' AS amount UNION ALL
  SELECT 'n/a' UNION ALL
  SELECT '17'
)
SELECT SUM(CAST(amount AS INT64)) AS total
FROM raw
Error in BigQuery

Bad int64 value: n/a

SAFE_CAST returns NULL for the value it can’t convert, and the query finishes:

SAFE_CAST turns 'n/a' into NULL
12345678
WITH raw AS (
  SELECT '42' AS amount UNION ALL
  SELECT 'n/a' UNION ALL
  SELECT '17'
)
SELECT amount, SAFE_CAST(amount AS INT64) AS parsed
FROM raw
ORDER BY amount
Result in BigQuery
amountparsed
11717
24242
3n/anull
3 rows

The NULLs then disappear quietly in SUM and AVG. Before you rely on SAFE_CAST, find out what is failing. A value that isn’t NULL but casts to NULL is a bad value:

list the values that don't cast
12345678
WITH raw AS (
  SELECT '42' AS amount UNION ALL
  SELECT 'n/a' UNION ALL
  SELECT '17'
)
SELECT amount AS bad_value
FROM raw
WHERE amount IS NOT NULL AND SAFE_CAST(amount AS INT64) IS NULL
Result in BigQuery
bad_value
1n/a
1 row

Division

Dividing by zero is an error, not NULL or infinity:

10 / 0BigQuery rejects this query
1
SELECT 10 / 0 AS ratio
Error in BigQuery

division by zero: 10 / 0

There are three ways around it, each with a different result for zero:

SAFE_DIVIDE, IEEE_DIVIDE and NULLIF
12345
SELECT
  SAFE_DIVIDE(10, 0) AS safe_divide,
  SAFE_DIVIDE(10, 4) AS normal,
  IEEE_DIVIDE(10, 0) AS ieee_divide,
  10 / NULLIF(0, 0) AS nullif_trick
Result in BigQuery
safe_dividenormalieee_dividenullif_trick
1null2.5Infinitynull
1 row
  • SAFE_DIVIDE(x, y) returns NULL when y is 0. This is the one to use for ratios in reports.
  • IEEE_DIVIDE(x, y) follows floating-point rules and returns Infinity, -Infinity or NaN.
  • x / NULLIF(y, 0) works in any SQL dialect and also returns NULL.

Integer overflow

INT64 is BigQuery’s only integer type. Going past its maximum is an error:

the largest INT64 plus oneBigQuery rejects this query
1
SELECT 9223372036854775807 + 1 AS too_big
Error in BigQuery

Integer Overflow

SAFE_ADD, SAFE_SUBTRACT, SAFE_MULTIPLY and SAFE_NEGATE return NULL on overflow instead:

SAFE_ math functions on overflow
1234
SELECT
  SAFE_ADD(9223372036854775807, 1) AS overflow_add,
  SAFE_MULTIPLY(9223372036854775807, 2) AS overflow_multiply,
  SAFE_NEGATE(-9223372036854775808) AS overflow_negate
Result in BigQuery
overflow_addoverflow_multiplyoverflow_negate
1nullnullnull
1 row

The SAFE. prefix

Put SAFE. in front of a function name and it returns NULL instead of an error caused by its input values. It works with string, math, date, time, JSON and most other scalar functions:

February 30, a negative length, log(-1), broken JSON
12345
SELECT
  SAFE.PARSE_DATE('%Y-%m-%d', '2026-02-30') AS bad_date,
  SAFE.SUBSTR('bigquery', 0, -2) AS bad_length,
  SAFE.LOG(-1) AS bad_log,
  SAFE.PARSE_JSON('{oops') AS bad_json
Result in BigQuery
bad_datebad_lengthbad_logbad_json
1nullnullnullnull
1 row

What SAFE. doesn’t cover:

  • Errors in the arguments. SAFE. protects only the function itself. If an argument fails while it is computed, the query still fails:

    SAFE.SQRT(1 / 0)BigQuery rejects this query
    1
    SELECT SAFE.SQRT(1 / 0) AS still_fails
    Error in BigQuery

    division by zero: 1 / 0

  • Operators, CAST and EXTRACT. +, /, =, CAST and EXTRACT can’t take the prefix. Use SAFE_ADD, SAFE_DIVIDE and SAFE_CAST:

    SAFE.CAST is not a functionBigQuery rejects this query
    1
    SELECT SAFE.CAST('x' AS INT64) AS nope
    Error in BigQuery

    Function not found: `CAST`; Did you mean SAFE.last? at [1:8]

  • Aggregate, window and user-defined functions.

  • Errors unrelated to input values, such as running out of resources.

Failing on purpose

The opposite is sometimes what you want: stop a pipeline when the data is wrong, rather than load wrong numbers. ERROR(message) fails the query with your own message, which you can include in an IF or CASE:

stop on a negative amountBigQuery rejects this query
123456
WITH payments AS (
  SELECT 'p1' AS id, 30 AS amount UNION ALL
  SELECT 'p2', -5
)
SELECT id, IF(amount >= 0, amount, ERROR(FORMAT('negative amount in %s', id))) AS amount
FROM payments
Error in BigQuery

negative amount in p2

As a statement of its own, ASSERT condition AS 'message' does the same, which is handy between the steps of a script. See Scripting.

Failed queries are free

A query that fails isn’t billed. So a cast error at the end of a long query costs time, not money. See How a query is billed.