apache/cassandra · error · InvalidRequestException
Unknown node
Error message
Unknown node
What it means
INSERT/UPDATE (apply) into the virtual table uses the partition key as a numeric NodeId. ClusterMetadata.directory has no endpoint registered for that id, so the write cannot be routed and InvalidRequestException is thrown.
Solutions
- Look up valid node ids (e.g. from the corresponding system virtual table or nodetool status) and use one of those as the partition key.
- If targeting a restarted cluster, re-fetch node ids — ids are not stable across topology changes.
- Verify the target node is still a member: ClusterMetadata.current().directory should contain it.
- Correct the integer value; node ids are internal, not user-chosen.
Example fix
// before INSERT INTO vt (node_id, ...) VALUES (42, ...); // 42 not in cluster // after INSERT INTO vt (node_id, ...) VALUES (1, ...); // id fetched from directory/status
Defensive patterns
Strategy: validation
Validate before calling
int nodeId = ...;
InetAddressAndPort ep = ClusterMetadata.current().directory.endpoint(new NodeId(nodeId));
if (ep == null) throw new IllegalArgumentException("Unknown node " + nodeId + "; fetch valid ids from the directory"); Try / catch
try { session.execute(write); }
catch (InvalidRequestException e) {
if (e.getMessage().startsWith("Unknown node"))
// refresh node id list and retry with a valid id
}
Prevention
- Fetch node ids dynamically, never hard-code them
- Re-fetch ids after any topology change (decommission/bootstrap/restart)
- Cross-check ids against nodetool status or the directory
- Validate the id exists before issuing the write
When it happens
Trigger: Writing to the virtual table with a partition key that is not a currently registered node id (typo, stale id of a removed node, wrong integer).
Common situations: Scripts caching node ids across cluster restarts; writes targeting a node after it was decommissioned/removenode'd; manual experimentation with arbitrary ids.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Can only unset '" + name + "'
- Cannot filter this table by partial partition key
- Cannot update '" + name + "'
- metadata + " currently only supports querying single…
- Modification is not supported by table " + metadata
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/73a5128d6fddc165.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/virtual/RemoteToLocalVirtualTable.java:501
private static void addExpressions(RowFilter rowFilter, List<ColumnMetadata> cms, int start, ByteBuffer[] values, Operator op, Operator lastOp)
{
for (int i = start ; i < values.length ; ++i)
rowFilter.add(cms.get(i), i + 1 == values.length ? lastOp : op, values[i]);
}
private static ClusteringIndexSliceFilter filter(TableMetadata metadata, ClusteringBound<?> start, ClusteringBound<?> end, boolean reversed)
{
return new ClusteringIndexSliceFilter(Slices.with(metadata.comparator, Slice.make(start, end)), reversed);
}
@Override
public void apply(PartitionUpdate update)
{
int nodeId = Int32Type.instance.compose(update.partitionKey().getKey());
InetAddressAndPort endpoint = ClusterMetadata.current().directory.endpoint(new NodeId(nodeId));
if (endpoint == null)
throw new InvalidRequestException("Unknown node " + nodeId);
DeletionInfo deletionInfo = update.deletionInfo();
if (!deletionInfo.getPartitionDeletion().isLive())
{
truncate(endpoint).syncThrowUncheckedOnInterrupt();
return;
}
int pkCount = local.partitionKeyColumns().size();
ByteBuffer[] pkBuffer, ckBuffer;
{
int ckCount = local.clusteringColumns().size();
pkBuffer = pkCount == 1 ? null : new ByteBuffer[pkCount];
ckBuffer = new ByteBuffer[ckCount];
}
PartitionUpdate.Builder builder = null;
ArrayDeque<Promise<Void>> results = new ArrayDeque<>();View on GitHub (pinned to 88fd0f6a0e)