{"record":{"id":"236c8db6b7d41301","repo":"atuinsh/atuin","slug":"failed-to-execute-script","errorCode":null,"errorMessage":"failed to execute script","messagePattern":"failed to execute script","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin/src/command/client/scripts.rs","lineNumber":163,"sourceCode":"            .args(args)\n            .arg(&path)\n            .status()?;\n        if !status.success() {\n            bail!(\"failed to open editor\");\n        }\n\n        // Read back the edited content\n        let content = std::fs::read_to_string(&path)?;\n        path.close()?;\n\n        Ok(content)\n    }\n\n    // Helper function to execute a script and manage stdin/stdout/stderr\n    async fn execute_script(script_content: String, shebang: String) -> Result<i32> {\n        let mut session = execute_script_interactive(script_content, shebang)\n            .await\n            .expect(\"failed to execute script\");\n\n        // Create a channel to signal when the process exits\n        let (exit_tx, mut exit_rx) = tokio::sync::oneshot::channel();\n\n        // Set up a task to read from stdin and forward to the script\n        let sender = session.stdin_tx.clone();\n        let stdin_task = tokio::spawn(async move {\n            use tokio::io::AsyncReadExt;\n            use tokio::select;\n\n            let stdin = tokio::io::stdin();\n            let mut reader = tokio::io::BufReader::new(stdin);\n            let mut buffer = vec![0u8; 1024]; // Read in chunks for efficiency\n\n            loop {\n                // Use select to either read from stdin or detect when the process exits\n                select! {\n                    // Check if the script process has exited","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/atuinsh/atuin/blob/202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1/crates/atuin/src/command/client/scripts.rs#L145-L181","documentation":"`atuin scripts run` writes the script to a temp file and executes it via execute_script_interactive (crates/atuin-scripts/src/execution.rs): first directly, then through the shebang interpreter as fallback. That helper returns Err when spawning fails — interpreter missing, ENOEXEC/EACCES (noexec /tmp), temp file creation failure, EMFILE — and execute_script immediately expects the Result, panicking with 'failed to execute script'.","triggerScenarios":"Running `atuin scripts run <name>` when the shebang interpreter does not exist locally (#!/usr/bin/env python3 without python3), /tmp is mounted noexec so direct execution fails and the interpreter fallback also fails, or the process lacks resources to spawn a child.","commonSituations":"Scripts synced from another machine naming an interpreter absent on this host; hardened containers with noexec TMPDIR; minimal images without bash or env.","solutions":["Verify the shebang interpreter exists (command -v python3) and fix the script's shebang via atuin scripts edit","If /tmp is noexec, remount exec or point TMPDIR at an exec-mounted filesystem","Inspect the stored script with `atuin scripts get <name> --script` to confirm its shebang and interpreter path"],"exampleFix":"# before — shebang names an interpreter absent on this host\n#!/usr/bin/env python3\n\n# after — use an interpreter present locally\n#!/usr/bin/env bash","handlingStrategy":"validation","validationCode":"fn interpreter_available(shebang: &str) -> bool {\n    let Some(bin) = shebang\n        .trim_start_matches(\"#!\")\n        .trim()\n        .split_whitespace()\n        .next()\n    else {\n        return false;\n    };\n    std::process::Command::new(bin).output().is_ok()\n}\n\nassert!(interpreter_available(&script.shebang), \"shebang interpreter is not installed\");","typeGuard":null,"tryCatchPattern":"// in a fork: propagate instead of panicking\nlet session = execute_script_interactive(script_content, shebang)\n    .await\n    .map_err(|e| eyre::eyre!(\"failed to execute script: {e}\"))?;","preventionTips":["Install every interpreter referenced by synced script shebangs before running them","Keep TMPDIR on an exec-mounted filesystem","Inspect `atuin scripts get <name> --script` when scripts arrive from other machines"],"tags":["scripts","subprocess","shebang","temp-file","panic"],"backgroundTag":"process-spawn-failed","analyzedSha":"202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1","analyzedAt":"2026-08-16T19:30:24.731Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}