influxdata/influxdb · error · TableIndexError

JSON serialization/deserialization failed

Error message

JSON serialization/deserialization failed

What it means

TableIndexError::Json wraps a serde_json::Error raised when serializing a TableIndexSnapshot to JSON before persisting it, or deserializing a PersistedSnapshot from JSON bytes read out of the object store. It means the snapshot payload could not be converted to/from JSON, typically because the stored bytes are corrupt, truncated, or written by an incompatible schema version.

Solutions

  1. Locate the offending snapshot file named in the operation log and check whether the JSON is complete and parseable (e.g. with jq).
  2. If the file is corrupt or from an incompatible older version, restore it from backup or remove/quarantine it so conversion can skip it, then restart.
  3. Ensure all InfluxDB 3 nodes in the deployment run a compatible version before/after upgrading; complete rolling upgrades rather than mixing versions.
  4. Rule out interrupted writes: verify upload/complete semantics and disk health on the object store.

Example fix

// before: manually copied a partially-uploaded snapshot file into the snapshot dir
// after: only fully-uploaded files are kept; verify first
jq . snapshot-0000001234.json >/dev/null || mv snapshot-0000001234.json /quarantine/
Defensive patterns

Strategy: validation

Validate before calling

// validate a snapshot file parses before conversion consumes it
fn validate_snapshot_json(bytes: &[u8]) -> Result<(), serde_json::Error> {
    serde_json::from_slice::<serde_json::Value>(bytes).map(|_| ())
}

Type guard

fn parse_snapshot(bytes: &[u8]) -> Option<PersistedSnapshotVersion> {
    serde_json::from_slice(bytes).ok()
}

Try / catch

match serde_json::from_slice::<PersistedSnapshotVersion>(&bytes) {
    Ok(s) => process(s),
    Err(e) => warn!("skipping corrupt snapshot: {e}; quarantine file"),
}

Prevention

When it happens

Trigger: serde_json::to_vec_pretty(self) fails inside TableIndexSnapshot::persist; serde_json::from_slice::<PersistedSnapshotVersion> fails inside TableIndexSnapshot::load_split_persist when loading a PersistedSnapshot during snapshot-format conversion.

Common situations: A PersistedSnapshot file truncated by a crash or interrupted upload, files written by an older InfluxDB 3 version whose schema no longer deserializes, or manual edits/corruption of files in the snapshot directory.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/d99356e90d67f8b5. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_write/src/table_index.rs:79

    #[error("Failed to update table index: join task failed")]
    UpdateTaskFailed(#[source] tokio::task::JoinError),

    #[error("Object meta is missing filename")]
    MissingFilename,

    #[error("Failed to parse snapshot sequence number from filename")]
    InvalidSnapshotSequenceNumber,

    #[error("Table snapshot persistence task failed")]
    TableSnapshotPersistenceTaskFailed(#[source] tokio::task::JoinError),

    #[error("Unexpected error")]
    Unexpected(#[source] anyhow::Error),

    #[error("Object store operation failed")]
    ObjectStore(#[source] object_store::Error),

    #[error("JSON serialization/deserialization failed")]
    Json(#[source] serde_json::Error),
}

pub type Result<T> = std::result::Result<T, TableIndexError>;

/// An partial, incremental index into a given database/table. Should not be used to make decisions
/// regarding gen1 file retention -- instead, all snapshots should be aggregated into a full
/// CoreTableIndex.
///
/// TableIndexSnapshots are expected to be created during the normal snapshotting process alongside
/// the full process-wide database + table index.
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
pub struct TableIndexSnapshot {
    #[serde(flatten)]
    pub id: TableIndexId,
    pub snapshot_sequence_number: SnapshotSequenceNumber,

    pub files: HashSet<ParquetFile>,

View on GitHub (pinned to 06200ef96b)