apache/cassandra · error · SyntaxError

Unknown direction

Error message

Unknown direction %s

What it means

Raised by the COPY command handler in cqlsh when the direction token of the COPY statement is neither FROM (import from CSV) nor TO (export to CSV). cqlsh raises a Python SyntaxError to reject the malformed statement before constructing an ImportTask or ExportTask. It is purely a user-input validation error.

Solutions

  1. Rewrite the COPY statement with an explicit valid direction: `COPY ks.table (cols) FROM 'file.csv' WITH opts;` or `... TO 'file.csv' ...`.
  2. Check that the direction token is the literal word FROM or TO (case-insensitive) immediately after the column list.
  3. If scripting, validate the direction variable before interpolating it into the COPY statement.

Example fix

// before
COPY myks.mytable frm 'data.csv';
// after
COPY myks.mytable FROM 'data.csv';
Defensive patterns

Strategy: validation

Validate before calling

direction = direction.strip().upper()
if direction not in ('FROM', 'TO'):
    raise ValueError('COPY direction must be FROM or TO, got %r' % direction)

Try / catch

try:
    shell.do_copy(parsed)
except SyntaxError as e:
    print('COPY statement rejected:', e)

Prevention

When it happens

Trigger: Running `COPY ks.tbl <direction> ...` where the direction keyword is misspelled, lowercased without matching, or missing (e.g. `COPY ks.tbl TO FROM`, `COPY ... frm`, or a direction binding that upper()s to something other than FROM/TO).

Common situations: Typo in COPY direction (e.g. `T0`, `form`); scripts generated programmatically with a missing or extra token; pasting partial COPY statements; confusion between COPY direction and file path ordering.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at pylib/cqlshlib/cqlshmain.py:1443

        else:
            # default to all known columns
            columns = self.get_column_names(ks, table)

        fname = parsed.get_binding('fname', None)
        if fname is not None:
            fname = self.cql_unprotect_value(fname)

        copyoptnames = list(map(str.lower, parsed.get_binding('optnames', ())))
        copyoptvals = list(map(self.cql_unprotect_value, parsed.get_binding('optvals', ())))
        opts = dict(list(zip(copyoptnames, copyoptvals)))

        direction = parsed.get_binding('dir').upper()
        if direction == 'FROM':
            task = ImportTask(self, ks, table, columns, fname, opts, self.conn.protocol_version, self.config_file)
        elif direction == 'TO':
            task = ExportTask(self, ks, table, columns, fname, opts, self.conn.protocol_version, self.config_file)
        else:
            raise SyntaxError("Unknown direction %s" % direction)

        task.run()

    def do_show(self, parsed):
        """
        SHOW [cqlsh only]

          Displays information about the current cqlsh session. Can be called in
          the following ways:

        SHOW VERSION

          Shows the version and build of the connected Cassandra instance, as
          well as the version of the CQL spec that the connected Cassandra
          instance understands.

        SHOW HOST

View on GitHub (pinned to 88fd0f6a0e)