clockworklabs/SpacetimeDB · error · RangeError
Timestamp is outside of the representable range for ISO…
Error message
Timestamp is outside of the representable range for ISO string formatting
What it means
The SpacetimeType/table derive machinery maps Rust items onto SATS types: structs become product types and enums become sum types. syn::Data::Union has no SATS representation, so deriving on a union is rejected with a span on the union token.
Solutions
- Convert the union to an enum whose variants carry each alternative's payload — enums are fully supported sum types.
- If the union is only a local layout trick, remove the derive and keep it out of the schema; store a representable type in tables instead.
Example fix
// before
#[derive(SpacetimeType)]
union Value { i: i64, f: f64 }
// after
#[derive(SpacetimeType)]
enum Value { Int(i64), Float(f64) } Defensive patterns
Strategy: validation
Validate before calling
# CI check: no derives on unions rg -nU '#\[(derive\([^)]*SpacetimeType|spacetimedb::table[^\]]*\)\]\s*(pub\s+)?union' src/ && exit 1 || true
Prevention
- Model alternatives as enums (sum types), never unions, in schema types.
- Keep unions confined to non-schema code; do not attach SpacetimeDB derives to them.
When it happens
Trigger: Applying #[derive(SpacetimeType)] / #[spacetimedb::spacetimedb_type] (or the table attribute, which routes through the same code) to a union item.
Common situations: Porting FFI-style code that uses unions for memory layouts; expecting a union to serialize like an untagged variant.
Related errors
- Cannot convert to : expected bigint, integer number, or…
- Invalid UUID: must be between 0 and `MAX_UUID_BIGINT`
- must specify view accessor, e.g. `#
- scheduled tables must have a `#[primary_key] #[auto_inc]…
- Timestamp is outside of the representable range of JS's Date
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/570e20009c6a361d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-typescript/src/lib/timestamp.ts:133
}
/**
* Get an ISO 8601 / RFC 3339 formatted string representation of this timestamp with microsecond precision.
*
* This method preserves the full microsecond precision of the timestamp,
* and throws `RangeError` if the `Timestamp` is outside the range representable in ISO format.
*
* @returns ISO 8601 formatted string with microsecond precision (e.g., '2025-02-17T10:30:45.123456Z')
*/
toISOString(): string {
const micros = this.__timestamp_micros_since_unix_epoch__;
const millis = micros / Timestamp.MICROS_PER_MILLIS;
if (
millis > BigInt(Number.MAX_SAFE_INTEGER) ||
millis < BigInt(Number.MIN_SAFE_INTEGER)
) {
throw new RangeError(
'Timestamp is outside of the representable range for ISO string formatting'
);
}
const date = new Date(Number(millis));
const isoBase = date.toISOString(); // Format: '2025-02-17T10:30:45.123Z'
// Extract the full 6 decimal places of microseconds
const microsRemainder = Math.abs(Number(micros % 1000000n));
const fractionalPart = String(microsRemainder).padStart(6, '0');
// Replace the 3-digit millisecond part with the full 6-digit microsecond part
return isoBase.replace(/\.\d{3}Z$/, `.${fractionalPart}Z`);
}
since(other: Timestamp): TimeDuration {
return new TimeDuration(
this.__timestamp_micros_since_unix_epoch__ -View on GitHub (pinned to 6dee26c6ef)