{"record":{"id":"c44e2ebe4b9381c4","repo":"linera-io/linera-protocol","slug":"block-timestamp-new-must-not-be-earlier-than-the","errorCode":null,"errorMessage":"Block timestamp {new} must not be earlier than the parent block's timestamp {parent}","messagePattern":"Block timestamp (.+?) must not be earlier than the parent block's timestamp (.+?)","errorType":"validation","errorClass":"ChainError","httpStatus":null,"severity":"error","filePath":"linera-chain/src/chain.rs","lineNumber":1312,"sourceCode":"        execution: BlockExecution,\n    ) -> Result<\n        (\n            ProposedBlock,\n            BlockExecutionOutcome,\n            ResourceTracker,\n            HashSet<ChainId>,\n        ),\n        ChainError,\n    > {\n        assert_eq!(\n            block.chain_id,\n            self.execution_state.context().extra().chain_id()\n        );\n\n        self.initialize_if_needed(local_time).await?;\n\n        let chain_timestamp = self.execution_state.system.progress.get().timestamp;\n        ensure!(\n            chain_timestamp <= block.timestamp,\n            ChainError::InvalidBlockTimestamp {\n                parent: chain_timestamp,\n                new: block.timestamp\n            }\n        );\n        ensure!(!block.transactions.is_empty(), ChainError::EmptyBlock);\n\n        ensure!(\n            block.published_blob_ids()\n                == published_blobs\n                    .iter()\n                    .map(|blob| blob.id())\n                    .collect::<BTreeSet<_>>(),\n            ChainError::InternalError(\"published_blobs mismatch\".to_string())\n        );\n\n        if *self.execution_state.system.closed.get() {","sourceCodeStart":1294,"sourceCodeEnd":1330,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-chain/src/chain.rs#L1294-L1330","documentation":"execute_block (linera-chain/src/chain.rs:1311-1318) rejects a block whose timestamp is earlier than the chain's current timestamp, read from system.progress — the parent block's timestamp. Timestamps must be monotonically non-decreasing along a chain; a child cannot be timestamped before its parent.","triggerScenarios":"Explicitly setting ProposedBlock.timestamp below the parent's timestamp; a client machine whose clock lags behind the timestamp of the last confirmed block; test code reusing fixed timestamps while the chain has advanced past them.","commonSituations":"Overriding timestamps instead of using the client default (which computes max(parent timestamp, local time)); VM clock drift on the proposing node; deterministic-test fixtures with hardcoded times replayed against advanced chains.","solutions":["Let the block timestamp default — the client derives it as at least the parent's timestamp and local time","If setting it manually, first query the chain's current timestamp and use block.timestamp >= that value","If caused by local clock skew, sync the machine's clock (NTP) and retry"],"exampleFix":"// before: explicit timestamp that may predate the parent\nlet block = ProposedBlock { timestamp: my_chosen_ts, .. };\n\n// after: clamp to the chain's current (parent) timestamp\nlet chain_ts = client.chain_info(chain_id).await?.info.system_timestamp;\nlet block = ProposedBlock { timestamp: my_chosen_ts.max(chain_ts), .. };","handlingStrategy":"validation","validationCode":"// Before proposing, clamp the timestamp to the chain's current one:\nlet chain_ts = client.chain_info(chain_id).await?.info.system_timestamp; // parent's timestamp\nif block.timestamp < chain_ts {\n    block.timestamp = chain_ts; // or chain_ts.max(local_time)\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(ChainError::InvalidBlockTimestamp { parent, new }) => {\n        // set block.timestamp = parent (or later) and re-propose\n    }\n    other => other?,\n}","preventionTips":["Use the client's default timestamp derivation instead of setting one","Keep proposer clocks NTP-synced to avoid drifting behind the chain","In tests, base timestamps on the chain's last timestamp, not constants"],"tags":["linera","timestamp","block","monotonicity","rust"],"backgroundTag":"block-timestamp-before-parent","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}