risingwavelabs/risingwave · error
Fast insert failed
Error message
Fast insert failed: {} What it means
The webhook handler sent a fast-insert request to the compute node and the response status was not Succeeded. The compute node's error_message is embedded in the returned error with HTTP 500. It means the batched fast path for writing webhook payload rows into the table failed on the compute side.
Solutions
- Inspect the embedded res.error_message in the error/response body for the root cause.
- Verify the webhook payload matches the table's expected JSON schema (column names/types).
- Check compute node health/logs (risingwave compute) and retry the POST.
- Confirm the table's webhook source is healthy: SELECT * FROM rw_catalog.rw_webhook_source_info (or equivalent) and re-create the webhook source if corrupted.
Example fix
// before
// compute rejects rows: wrong column type
POST /webhook/table/orders {"amount": "not-a-number"}
// after
POST /webhook/table/orders {"amount": 42} Defensive patterns
Strategy: try-catch
Validate before calling
// validate payload against the table schema before POST
const required = ['id', 'amount'];
if (!required.every(k => k in payload) || typeof payload.amount !== 'number') {
throw new Error('payload does not match table schema');
} Type guard
function isValidWebhookPayload(p: unknown): p is Record<string, string|number|boolean|null> {
return typeof p === 'object' && p !== null && !Array.isArray(p);
} Try / catch
try {
await postWebhook('/table/orders', payload);
} catch (e) {
if (e.status === 500 && /Fast insert failed/.test(e.message)) {
logComputeError(e.message); // includes res.error_message
await retryWithBackoff(() => postWebhook('/table/orders', payload));
} else { throw e; }
} Prevention
- Match payload keys and types to the table schema exactly.
- Monitor compute node health before high-volume webhook traffic.
- Implement client-side retries with backoff for 500s.
- Keep the embedded compute error_message in your logs for triage.
When it happens
Trigger: POSTing to a webhook endpoint /table where handle_post_request executes the fast insert and res.status != Succeeded: compute node unreachable/overloaded, schema mismatch between payload columns and table, or serialization failure inside the compute node.
Common situations: Webhook payloads whose extracted columns don't match the table schema; compute node crash/restart under load; MV built over the webhook source rejecting rows; network partition between frontend and compute.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- failed to build webhook JSON decoder
- Failed to choose a compute node for fast insert
- failed to execute on the compute node
- Insert error: , error url
- Can't find data
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/15dd95f1b8b5c8e9.
Report an issue: GitHub.
Appendix: source
Thrown at src/frontend/src/webhook/mod.rs:178
}
};
let fast_insert_request = FastInsertRequest {
table_id,
table_version_id,
data_chunk: Some(data_chunk.to_protobuf()),
row_id_index,
request_id,
wait_for_persistence: webhook_source_info.wait_for_persistence,
};
// execute on the compute node
let res = execute(fast_insert_request, compute_client).await?;
if res.status == fast_insert_response::Status::Succeeded as i32 {
Ok(())
} else {
Err(err(
anyhow!("Fast insert failed: {}", res.error_message),
StatusCode::INTERNAL_SERVER_ERROR,
))
}
}
fn generate_data_chunk(is_batched: bool, body: &Bytes) -> Result<DataChunk> {
let mut builder = JsonbArrayBuilder::with_type(1, DataType::Jsonb);
if !is_batched {
// Use builder to obtain a single column & single row DataChunk
let json_value = Value::from_text(body).map_err(|e| {
err(
anyhow!(e).context("failed to parse request body"),
StatusCode::UNPROCESSABLE_ENTITY,
)
})?;
let jsonb_val = JsonbVal::from(json_value);View on GitHub (pinned to 6469eb736d)