apache/cassandra · error · ParseError

Cannot insert null value for primary key column '%s'.

Error message

Cannot insert null value for primary key column '%s'.

What it means

COPY FROM rejects rows where a primary key column (partition key or clustering column) contains the nullval marker, since null primary keys cannot be inserted. The raised message names the offending column via get_null_primary_key_message.

Source

Thrown at pylib/cqlshlib/copyutil.py:2167

        or "NULL" otherwise. Note that for counters we never use prepared statements, so we
        only check is_counter when use_prepared_statements is false.
        """
        return None if self.use_prepared_statements else ("0" if self.is_counter else "NULL")

    def convert_row(self, row):
        """
        Convert the row into a list of parsed values if using prepared statements, else simply apply the
        protection functions to escape values with quotes when required. Also check on the row length and
        make sure primary partition key values aren't missing.
        """
        converters = self.converters if self.use_prepared_statements else self.protectors

        if len(row) != len(converters):
            raise ParseError('Invalid row length %d should be %d' % (len(row), len(converters)))

        for i in self.primary_key_indexes:
            if row[i] == self.nullval:
                raise ParseError(self.get_null_primary_key_message(i))

        def convert(c, v):
            try:
                return c(v) if v != self.nullval else self.get_null_val()
            except Exception as e:
                # if we could not convert an empty string, then self.nullval has been set to a marker
                # because the user needs to import empty strings, except that the converters for some types
                # will fail to convert an empty string, in this case the null value should be inserted
                # see CASSANDRA-12794
                if v == '':
                    return self.get_null_val()

                if self.debug:
                    traceback.print_exc()
                raise ParseError("Failed to parse %s : %s" % (v, e.message if hasattr(e, 'message') else str(e)))

        return [convert(conv, val) for conv, val in zip(converters, row)]

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Fill in the missing primary key values in the CSV
  2. If empty-string keys are meaningful, choose a different NULLS marker that does not appear in key columns
  3. Skip/filter rows with empty primary keys before importing

Example fix

// before (CSV)
,2026-01-01,value
// after
key1,2026-01-01,value
Defensive patterns

Strategy: validation

Validate before calling

pk_indexes = [0, 1]
for i, row in enumerate(rows, 1):
    for j in pk_indexes:
        if row[j] in ('', null_marker):
            raise ValueError(f"line {i}: null primary key col {j}")

Try / catch

try:
    run_copy_from(...)
except ParseError as e:
    print(f"Null primary key: {e}")  # supply key or skip row

Prevention

When it happens

Trigger: COPY FROM a CSV row whose partition key or clustering key cell equals the null marker (default empty string), e.g. an empty first field; the nullval may also be a custom marker set by WITH NULLS.

Common situations: CSVs produced by exports that padded missing keys with empty cells, joins/spreadsheets that blanked key columns, NULLS option colliding with real key values, rows appended with empty keys.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/4fafd091ae3c1667. Report an issue: GitHub.