sinelaw/fresh · error

could not open : no tokio runtime available for container…

Error message

could not open {}: no tokio runtime available for container fetch

What it means

fetch_and_open_container_file runs `cat <path>` inside the container via tokio's block_on. It requires a tokio runtime stored on the app state; when self.tokio_runtime is None (headless/early startup or a build without the runtime initialized) the container fetch cannot be performed and this error is thrown.

Solutions

  1. Ensure the tokio runtime is created during app startup before any remote/container authority is activated
  2. Guard container-mode features behind runtime availability and disable them with a clear message when absent
  3. In tests, construct the runtime (tokio::runtime::Runtime::new()) and inject it into app state
  4. Audit initialization order after refactors so tokio_runtime is set before handle_goto_definition_response can fire

Example fix

// before
let buffer_id = self.fetch_and_open_container_file(container_path, uri.clone())?;
// after
if self.tokio_runtime.is_none() {
    log::error!("container fetch unavailable: runtime not initialized");
    return Ok(self.active_buffer_id());
}
let buffer_id = self.fetch_and_open_container_file(container_path, uri.clone())?;
Defensive patterns

Strategy: type-guard

Validate before calling

if app.tokio_runtime.is_none() {
    disable_container_features();
}

Type guard

fn has_container_fetch(app: &App) -> bool {
    app.tokio_runtime.is_some()
}

Try / catch

match self.open_lsp_uri_target(&uri) {
    Err(e) if e.to_string().contains("no tokio runtime") => {
        log::error!("container fetch disabled: runtime not initialized");
    }
    other => other?,
}

Prevention

When it happens

Trigger: goto-definition resolves to a container-only file while the application was constructed without initializing tokio_runtime — e.g. remote/container mode entered before the async runtime was set up, or a code path that bypasses runtime initialization.

Common situations: Devcontainer workflows started through a code path that skips runtime setup; tests instantiating the app state manually without a runtime; regression after refactoring app initialization order.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/3e8ebdc25571595a. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/src/app/file_open_orchestrators.rs:740

        ))
    }

    /// Run `cat <container_path>` through the active authority's
    /// process spawner and open the result as a read-only buffer
    /// tagged with the wire URI. Helper for [`Self::open_lsp_uri_target`].
    ///
    /// On `cat` exit-code 0 the bytes become the buffer's contents.
    /// On any error (no tokio runtime, spawner failure, non-zero
    /// exit) we return `Err` with a message that includes the
    /// container path and stderr's first line — enough for the
    /// caller's status-line surface.
    fn fetch_and_open_container_file(
        &mut self,
        container_path: std::path::PathBuf,
        uri: crate::app::types::LspUri,
    ) -> anyhow::Result<BufferId> {
        let runtime = self.tokio_runtime.as_ref().ok_or_else(|| {
            anyhow::anyhow!(
                "could not open {}: no tokio runtime available for container fetch",
                container_path.display()
            )
        })?;

        let spawner = self.authority().process_spawner.clone();
        let path_arg = container_path.to_string_lossy().into_owned();
        let result = runtime
            .block_on(spawner.spawn("cat".into(), vec![path_arg], None))
            .map_err(|e| {
                anyhow::anyhow!(
                    "could not open {} from container: {}",
                    container_path.display(),
                    e
                )
            })?;

        if result.exit_code != 0 {

View on GitHub (pinned to 67894ca546)