{"record":{"id":"e316502c8ab805f1","repo":"risingwavelabs/risingwave","slug":"logicalnow-can-only-be-converted-to-stream","errorCode":null,"errorMessage":"`LogicalNow` can only be converted to stream","messagePattern":"`LogicalNow` can only be converted to stream","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/optimizer/plan_node/logical_now.rs","lineNumber":98,"sourceCode":"    fn logical_rewrite_for_stream(\n        &self,\n        _ctx: &mut RewriteStreamContext,\n    ) -> Result<(PlanRef, ColIndexMapping)> {\n        Ok((self.clone().into(), ColIndexMapping::new(vec![Some(0)], 1)))\n    }\n\n    /// `to_stream` is equivalent to `to_stream_with_dist_required(RequiredDist::Any)`\n    fn to_stream(\n        &self,\n        _ctx: &mut ToStreamContext,\n    ) -> Result<crate::optimizer::plan_node::StreamPlanRef> {\n        Ok(StreamNow::new(self.core.clone()).into())\n    }\n}\n\nimpl ToBatch for LogicalNow {\n    fn to_batch(&self) -> Result<crate::optimizer::plan_node::BatchPlanRef> {\n        bail!(\"`LogicalNow` can only be converted to stream\")\n    }\n}\n\n/// The trait for column pruning, only logical plan node will use it, though all plan node impl it.\nimpl ColPrunable for LogicalNow {\n    fn prune_col(&self, required_cols: &[usize], _: &mut ColumnPruningContext) -> PlanRef {\n        if required_cols.is_empty() {\n            LogicalValues::new(vec![], Schema::empty().clone(), self.ctx()).into()\n        } else {\n            assert_eq!(required_cols, &[0], \"we only output one column\");\n            self.clone().into()\n        }\n    }\n}\n","sourceCodeStart":80,"sourceCodeEnd":113,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/optimizer/plan_node/logical_now.rs#L80-L113","documentation":"LogicalNow represents the non-deterministic now() function. In RisingWave, now() is only meaningful in streaming plans (where it is materialized as a streaming expression with provisional/refresh semantics); there is no batch lowering, so to_batch explicitly errors. For batch queries users should use CURRENT_TIMESTAMP (fixed at query start) instead.","triggerScenarios":"Calling to_batch on a plan containing LogicalNow — typically using now() inside a batch SELECT, batch DML, or a query path that is forced through batch optimization (e.g. inside a batch exec of a DML statement where now() was not rewritten).","commonSituations":"Users write INSERT ... SELECT now() or batch SELECT now() expecting wall-clock time; frontend rewrites usually substitute CURRENT_TIMESTAMP for now() in batch contexts, and this error surfaces when a now() survives into batch optimization.","solutions":["Use CURRENT_TIMESTAMP instead of now() in batch queries","In INSERT ... SELECT batch statements, replace now() with CURRENT_TIMESTAMP","Check frontend rewrite rules if you maintain the codebase: ensure now() in batch contexts is rewritten to CurrentTimestamp before ToBatch","If it appears in a materialized view path that unexpectedly goes batch, verify the query is not being forced into batch mode"],"exampleFix":"-- before (fails in batch)\nSELECT now();\nINSERT INTO t SELECT now(), ...;\n-- after\nSELECT CURRENT_TIMESTAMP;\nINSERT INTO t SELECT CURRENT_TIMESTAMP, ...;","handlingStrategy":"validation","validationCode":"-- In batch queries, always use CURRENT_TIMESTAMP instead of now()\n-- static check in app code:\n-- if /\\bnow\\s*\\(\\s*\\)/i.test(batchSql) throw new Error('use CURRENT_TIMESTAMP in batch queries');","typeGuard":null,"tryCatchPattern":"try {\n  await conn.query('SELECT now()');\n} catch (e) {\n  if (String(e.message).includes('`LogicalNow` can only be converted to stream')) {\n    await conn.query('SELECT CURRENT_TIMESTAMP');\n  } else { throw e; }\n}","preventionTips":["Use now() only inside materialized views / streaming queries","Use CURRENT_TIMESTAMP for batch and INSERT ... SELECT statements","Lint SQL for now() in batch execution paths"],"tags":["rust","batch","now","non-determinism"],"backgroundTag":"unsupported-operation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}