Files
attune/work-summary/2026-02-nodejs-runtime-fix.md

4.3 KiB

Node.js Runtime Fix

Date: 2026-02 Scope: Worker runtime loading, environment setup, action execution

Problem

Node.js actions from installed packs (e.g., nodejs_example) were stuck in "In Progress" status and never completing. Three root causes were identified:

1. Runtime Name Mismatch (Blocking)

The ATTUNE_WORKER_RUNTIMES env var for the node worker is shell,node, but the database runtime name is "Node.js" which lowercases to "node.js". The worker's filter used exact string matching (filter.contains(&rt_name)), so "node.js" was never found in ["shell", "node"]. The Node.js ProcessRuntime was never registered, meaning no worker could handle Node.js executions.

2. Broken Environment Setup

The Node.js execution_config in packs/core/runtimes/nodejs.yaml had:

  • create_command: ["npm", "init", "-y"] — ran in the pack directory (read-only in Docker), didn't create anything at {env_dir}
  • install_command: ["npm", "install", "--prefix", "{pack_dir}"] — tried to write node_modules into the read-only pack directory

3. Missing NODE_PATH

Even with correct installation, Node.js couldn't find modules installed at {env_dir}/node_modules because Node resolves modules relative to the script location, not the environment directory. No mechanism existed to set NODE_PATH during execution.

Solution

Runtime Name Normalization

Added normalize_runtime_name() and runtime_in_filter() to crates/common/src/runtime_detection.rs. These functions map common aliases to canonical names:

  • node / nodejs / node.jsnode
  • python / python3python
  • shell / bash / shshell
  • native / builtin / standalonenative

Updated crates/worker/src/service.rs and crates/worker/src/env_setup.rs to use runtime_in_filter() instead of exact string matching.

RuntimeExecutionConfig.env_vars

Added an env_vars: HashMap<String, String> field to RuntimeExecutionConfig in crates/common/src/models.rs. Values support the same template variables as other fields ({env_dir}, {pack_dir}, {interpreter}, {manifest_path}).

In ProcessRuntime::execute (crates/worker/src/runtime/process.rs), runtime env_vars are resolved and injected into the action's environment before building the command.

Fixed Node.js Runtime Config

Updated packs/core/runtimes/nodejs.yaml and scripts/seed_runtimes.sql:

execution_config:
  interpreter:
    binary: node
    args: []
    file_extension: ".js"
  environment:
    env_type: node_modules
    dir_name: node_modules
    create_command:
      - sh
      - "-c"
      - "mkdir -p {env_dir} && cp {manifest_path} {env_dir}/ 2>/dev/null || true"
    interpreter_path: null
  dependencies:
    manifest_file: package.json
    install_command:
      - npm
      - install
      - "--prefix"
      - "{env_dir}"
  env_vars:
    NODE_PATH: "{env_dir}/node_modules"

Files Changed

File Change
crates/common/src/models.rs Added env_vars field to RuntimeExecutionConfig
crates/common/src/runtime_detection.rs Added normalize_runtime_name(), runtime_matches_filter(), runtime_in_filter() with tests
crates/worker/src/service.rs Use runtime_in_filter() for ATTUNE_WORKER_RUNTIMES matching
crates/worker/src/env_setup.rs Use runtime_in_filter() for runtime filter matching in env setup
crates/worker/src/runtime/process.rs Inject env_vars into action environment during execution
crates/worker/src/runtime/local.rs Added env_vars field to fallback config
packs/core/runtimes/nodejs.yaml Fixed create_command, install_command, added env_vars
scripts/seed_runtimes.sql Fixed Node.js execution_config to match YAML
crates/worker/tests/*.rs Added env_vars field to test configs
AGENTS.md Documented runtime name normalization, env_vars, and env setup requirements

Testing

  • All 424 unit tests pass
  • Zero compiler warnings
  • New tests for normalize_runtime_name, runtime_matches_filter, runtime_in_filter

Deployment Notes

After deploying, the Node.js runtime config in the database needs to be updated. This happens automatically when packs are re-registered (the pack loader reads the updated YAML). Alternatively, run the updated seed_runtimes.sql script.