clockworklabs/SpacetimeDB · error
Precheck failed: added sequence {sequence_name} has invalid
Error message
Precheck failed: added sequence {sequence_name} has invalid max value What it means
Auto-migrate precheck: converting the sequence's max value (explicit sequence_def.max_value, or i128::MAX when unset) into the sequenced column's type via saturating_value_from_i128 returned None, so the max is not representable in the column's algebraic type — practically a non-integer or incompatible sequenced column.
Source
Thrown at crates/engine/src/update.rs:248
.ok_or_else(|| {
anyhow::anyhow!("Precheck failed: added sequence {sequence_name} refers to unknown column")
})?
.ty
.clone();
// Convert `SequenceDef` min/max to `AlgebraicValue`s of the correct type.
let min = ty
.saturating_value_from_i128(sequence_def.min_value.unwrap_or(1))
.ok_or_else(|| {
anyhow::anyhow!("Precheck failed: added sequence {sequence_name} has invalid min value")
})?;
let max = match sequence_def.max_value {
Some(max) => ty.saturating_value_from_i128(max),
None => ty.saturating_value_from_i128(i128::MAX),
}
.ok_or_else(|| {
anyhow::anyhow!("Precheck failed: added sequence {sequence_name} has invalid max value")
})?;
let range = min..=max;
if stdb
.iter_by_col_range_mut(tx, table_id, sequence_def.column, range)?
.next()
.is_some()
{
anyhow::bail!("Precheck failed: added sequence {sequence_name} already has values in range",);
}
}
}
}
log::info!("Running database update steps: {}", stdb.database_identity());
let mut res = UpdateResult::Success;
for step in plan.steps {View on GitHub (pinned to 6dee26c6ef)
Solutions
- Choose a max_value representable by the column type, or drop the explicit max
- Ensure the sequenced column is an integer type (u64/i64 recommended)
- Validate sequence bounds against the column type in the module before publishing
Example fix
// before: max not representable for the column type #[sequence(column = "id", max = ...)] // id: u8 // after: widen the column or drop the custom max #[sequence(column = "id")] // id: u64
Defensive patterns
Strategy: validation
Validate before calling
// Check the declared max is representable for the column type
fn sequence_max_ok(col_ty: &AlgebraicType, max: Option<i128>) -> bool {
col_ty.saturating_value_from_i128(max.unwrap_or(i128::MAX)).is_some()
} Type guard
fn is_integer_col(ty: &AlgebraicType) -> bool {
matches!(t, AlgebraicType::U8 | AlgebraicType::U16 | AlgebraicType::U32
| AlgebraicType::U64 | AlgebraicType::U128 | AlgebraicType::I8
| AlgebraicType::I16 | AlgebraicType::I32 | AlgebraicType::I64 | AlgebraicType::I128)
} Try / catch
match auto_migrate_database(&stdb, &mut tx, auth, &plan, &logger) {
Err(e) if e.to_string().contains("invalid max value") => {
anyhow::bail!("module error: {e:#}; widen the column or drop the custom max");
}
r => r,
} Prevention
- Prefer leaving max unset on wide integer columns
- Cross-check custom bounds against the column type in CI module validation
- Avoid narrowing sequenced columns in publishes that also change sequences
When it happens
Trigger: Declaring max_value outside what the sequenced column's type can represent where saturation does not apply; adding a sequence on a column whose type cannot hold any i128-derived bound; narrowing the sequenced column in the same publish that adds the sequence.
Common situations: Custom max_value on a small or non-integer column; module defs edited by hand without type-checking the sequence bounds; schema crate version skew.
Related errors
- Precheck failed: added sequence {sequence_name} has invalid
- Precheck: sequence `{sequence_name}` not found in new module
- Precheck failed: added sequence {sequence_name} refers to un
- table {} not found in old_module_def
- AddTable: table `{table_name}` not found in new module def
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/0753349c95b44155.
Report an issue: GitHub.