apache/cassandra · error · IllegalArgumentException

Route index is only allowed for accord journal table, and on

Error message

Route index is only allowed for accord journal table, and on the record/user_value columns; given %s and columns %s

What it means

validateTargets throws this when the index is on accord.journal but the target columns are not exactly {record, user_version}. The comma-separated 'target' option is split, trimmed, and compared as a set against the required two columns; any extra, missing, or misspelled column fails.

Source

Thrown at src/java/org/apache/cassandra/index/accord/RouteJournalIndex.java:156

        return id.type == JournalKey.Type.COMMAND_DIFF && allowed(id.id);
    }

    public static boolean allowed(TxnId id)
    {
        return id.is(Range);
    }

    private static void validateTargets(ColumnFamilyStore baseCfs, IndexMetadata indexMetadata)
    {
        // this contains 2 columns....
        if (!SchemaConstants.ACCORD_KEYSPACE_NAME.equals(baseCfs.getKeyspaceName()))
            throw new IllegalArgumentException("Route index is only allowed for accord journal table; given " + baseCfs.metadata());
        if (!AccordKeyspace.JOURNAL.equals(baseCfs.name))
            throw new IllegalArgumentException("Route index is only allowed for accord journal table; given " + baseCfs.metadata());
        Set<String> columns = Splitter.on(',').trimResults().omitEmptyStrings().splitToStream(indexMetadata.options.get("target")).collect(Collectors.toSet());
        Set<String> expected = Set.of("record", "user_version");
        if (!expected.equals(columns))
            throw new IllegalArgumentException("Route index is only allowed for accord journal table, and on the record/user_value columns; given " + baseCfs.metadata() + " and columns " + columns);
    }

    public IndexMetrics indexMetrics()
    {
        return indexMetrics;
    }

    public RegisterStatus registerStatus()
    {
        return registerStatus;
    }

    public ColumnFamilyStore baseCfs()
    {
        return baseCfs;
    }

    @Override

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Set the target exactly to (record, user_version)
  2. Drop and recreate the index with both columns
  3. Inspect the existing index with DESCRIBE and correct the columns list

Example fix

// before
CREATE CUSTOM INDEX route_idx ON accord.journal (record) USING 'org.apache.cassandra.index.accord.RouteJournalIndex';
// after
CREATE CUSTOM INDEX route_idx ON accord.journal (record, user_version) USING 'org.apache.cassandra.index.accord.RouteJournalIndex';
Defensive patterns

Strategy: validation

Validate before calling

Set<String> cols = new HashSet<>(Arrays.asList(target.split(",")));
if (!Set.of("record", "user_version").equals(cols)) throw new IllegalStateException("RouteJournalIndex requires target columns record,user_version, got " + cols);

Try / catch

try { validateTargets(baseCfs, indexMetadata); } catch (IllegalArgumentException e) { /* recreate index with record,user_version */ }

Prevention

When it happens

Trigger: RouteJournalIndex created with target options other than 'record,user_version' — e.g. only 'record', extra columns, different column names, or a single-column target.

Common situations: Hand-writing the CREATE INDEX target string; changing journal schema assumptions; automation that generates target lists from table columns.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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