{"record":{"id":"a0ed8aaf2e0fcb71","repo":"risingwavelabs/risingwave","slug":"error-a0ed8a","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"error_code","errorClass":"StreamExecutorError","httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/error.rs","lineNumber":153,"sourceCode":"/// Connector error.\nimpl From<ConnectorError> for StreamExecutorError {\n    fn from(s: ConnectorError) -> Self {\n        Self::connector_error(s)\n    }\n}\n\nimpl From<PbFieldNotFound> for StreamExecutorError {\n    fn from(err: PbFieldNotFound) -> Self {\n        Self::from(anyhow::anyhow!(\n            \"Failed to decode prost: field not found `{}`\",\n            err.0\n        ))\n    }\n}\n\nimpl From<String> for StreamExecutorError {\n    fn from(s: String) -> Self {\n        ErrorKind::Uncategorized(anyhow::anyhow!(s)).into()\n    }\n}\n\nimpl From<(SinkError, SinkId)> for StreamExecutorError {\n    fn from((err, sink_id): (SinkError, SinkId)) -> Self {\n        ErrorKind::SinkError(err, sink_id).into()\n    }\n}\n\nimpl StreamExecutorError {\n    pub fn variant_name(&self) -> &str {\n        self.0.inner().as_ref()\n    }\n}\n\nstatic_assertions::const_assert_eq!(std::mem::size_of::<StreamExecutorError>(), 8);\n\n#[cfg(test)]","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/error.rs#L135-L171","documentation":"This From<String> impl (src/stream/src/executor/error.rs:151) turns an arbitrary String into a StreamExecutorError by wrapping it in ErrorKind::Uncategorized(anyhow::anyhow!(s)). The rendered message is just the string itself ('{}'), so the string becomes the entire error text. It is the generic entry point for ad-hoc error messages in executor code.","triggerScenarios":"Raised wherever a `?` on a `Result<_, String>` or an explicit `.into()`/`StreamExecutorError::from(String)` occurs in stream executor code, e.g. helper functions that report failures as plain strings.","commonSituations":"Legacy or quick internal error paths that return String messages; errors from utility code not using typed errors; dynamic messages assembled at runtime.","solutions":["Read the string message to find which executor code path produced it.","Replace String-based error returns in the source with typed errors for better diagnostics (maintainer-side fix).","Trace with the backtrace attached by the Uncategorized variant to locate the raise site.","Handle it as an unexpected internal error; restart/failover will typically recover the actor."],"exampleFix":"// before\nfn helper() -> Result<(), String> { ... Err(\"bad state\".to_string())? }\n// after\nfn helper() -> StreamExecutorResult<()> { ... bail!(\"bad state\") }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn is_string_error(e: &StreamExecutorError) -> bool {\n    // From<String> lands in Uncategorized; treat non-variant messages as ad-hoc\n    e.variant_name() == \"Uncategorized\"\n}","tryCatchPattern":"if let Err(e) = result {\n    if e.variant_name() == \"Uncategorized\" {\n        // the message IS the string passed to From<String>; log and fail over\n        tracing::error!(msg = %e, \"ad-hoc executor error\");\n    }\n    return Err(e);\n}","preventionTips":["Replace String-typed error returns in executor helpers with typed errors.","Use thiserror/thiserror_ext variants instead of raw strings for new code.","Attach context with anyhow::Context when constructing ad-hoc messages.","Grep for From<String> usages when auditing error paths."],"tags":["string-error","uncategorized","stream-executor"],"backgroundTag":"internal-invariant-violation","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"}