{"record":{"id":"184846295a904b98","repo":"quickwit-oss/quickwit","slug":"actor-is-disconnected","errorCode":null,"errorMessage":"actor `{}` is disconnected","messagePattern":"actor `(.+?)` is disconnected","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-codegen/src/codegen.rs","lineNumber":1111,"sourceCode":"                let tower_svc_stack = #tower_svc_stack_name {\n                    inner: inner_client,\n                    #(#svc_attribute_idents),*\n                };\n                #client_name::new(tower_svc_stack)\n            }\n        }\n    }\n}\n\nfn generate_tower_mailbox(context: &CodegenContext) -> TokenStream {\n    let service_name = &context.service_name;\n    let mailbox_name = &context.mailbox_name;\n    let error_type = &context.error_type;\n    let extra_mailbox_methods = if context.generate_extra_service_methods {\n        quote! {\n            async fn check_connectivity(&self) -> anyhow::Result<()> {\n                if self.inner.is_disconnected() {\n                    anyhow::bail!(\"actor `{}` is disconnected\", self.inner.actor_instance_id())\n                }\n                Ok(())\n            }\n\n            fn endpoints(&self) -> Vec<quickwit_common::uri::Uri> {\n                vec![quickwit_common::uri::Uri::from_str(&format!(\"actor://localhost/{}\", self.inner.actor_instance_id())).expect(\"URI should be valid\")]\n            }\n        }\n    } else {\n        TokenStream::new()\n    };\n\n    let (mailbox_bounds, mailbox_methods) = generate_mailbox_bounds_and_methods(context);\n\n    quote! {\n        #[derive(Debug, Clone)]\n        struct MailboxAdapter<A: quickwit_actors::Actor, E> {\n            inner: quickwit_actors::Mailbox<A>,","sourceCodeStart":1093,"sourceCodeEnd":1129,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-codegen/src/codegen.rs#L1093-L1129","documentation":"This error is emitted by generated code (quickwit-codegen) in the `check_connectivity` method of the mailbox-based client adapter for a gRPC service backed by an actor. When the underlying actor (e.g. the indexing service actor) is disconnected — its mailbox has been stopped or dropped — any call routed through this adapter cannot be delivered. The library throws it eagerly via `check_connectivity` so callers can detect the dead actor before issuing the actual request.","triggerScenarios":"Calling `check_connectivity()` on a generated mailbox client (e.g. IndexingService's MailboxIndexingService) after the target actor has been killed, exited with an error, or its ActorContext was stopped; or any service call that internally performs the connectivity check against a disconnected actor instance.","commonSituations":"Indexing pipeline actor crashed during startup, a node was shut down or restarted while clients still hold the mailbox handle, actor supervision was not restarted, or tests stopped the actor universe before making a final call.","solutions":["Check the actor's state/logs to determine why it stopped, and restart the actor (or the node) before retrying service calls.","Call `check_connectivity()` before issuing operations and treat the error as 'actor must be respawned', rebuilding the service handle after restart.","If the actor is expected to be ephemeral, wrap client calls in retry logic that re-resolves/re-creates the actor handle after observing this error.","In tests, ensure the actor universe is kept alive for the duration of the calls (hold the JoinHandle/supervisor)."],"exampleFix":"// before: calling a service whose actor was stopped\nlet resp = indexing_service.check_connectivity().await?;\n// after: verify and respawn the actor when disconnected\nif indexing_service.check_connectivity().await.is_err() {\n    let (_mailbox, actor_handle) = IndexingService::new(...).spawn();\n    // rebuild the client from the new mailbox before calling\n}","handlingStrategy":"try-catch","validationCode":"// Before issuing calls, check actor liveness\nif service_actor_mailbox.instance().is_disconnected() {\n    // restart actor or fail fast before making the call\n}","typeGuard":null,"tryCatchPattern":"match client.check_connectivity().await {\n    Ok(()) => { /* proceed with request */ }\n    Err(e) if e.to_string().contains(\"is disconnected\") => {\n        // respawn actor, rebuild client handle, then retry\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep the actor supervisor/JoinHandle alive for the client's lifetime.","Subscribe to the actor's lifecycle events and invalidate clients when the actor exits.","Call check_connectivity() before batch operations instead of per-request assumptions."],"tags":["actor","codegen","grpc","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}