Hmbown/CodeWhale · error · Error

CODEWHALE_SMOKE_ASSETS_DIR is not a directory: ${releaseAsse

Error message

CODEWHALE_SMOKE_ASSETS_DIR is not a directory: ${releaseAssetsDir}

What it means

The smoke test was pointed at preassembled release assets via CODEWHALE_SMOKE_ASSETS_DIR; fsp.stat() resolved the path but it is not a directory (a regular file or a symlink to a file, such as a packaged asset archive). Note: a nonexistent path fails earlier at stat() with ENOENT, not this error.

Source

Thrown at scripts/release/npm-wrapper-smoke.js:155

  const suppliedAssetsDir = String(
    process.env.CODEWHALE_SMOKE_ASSETS_DIR || "",
  ).trim();
  const releaseAssetsDir = suppliedAssetsDir
    ? path.resolve(suppliedAssetsDir)
    : path.join(tempRoot, "release-assets");
  const packDir = path.join(tempRoot, "pack");
  const installDir = path.join(tempRoot, "install");
  let keepTemp = process.env.DEEPSEEK_TUI_KEEP_SMOKE_DIR === "1";
  let server;

  try {
    await fsp.mkdir(packDir, { recursive: true });
    await fsp.mkdir(installDir, { recursive: true });

    if (suppliedAssetsDir) {
      const assetDirectoryStat = await fsp.stat(releaseAssetsDir);
      if (!assetDirectoryStat.isDirectory()) {
        throw new Error(`CODEWHALE_SMOKE_ASSETS_DIR is not a directory: ${releaseAssetsDir}`);
      }
      console.log(`Using preassembled release assets from ${releaseAssetsDir}`);
    } else {
      const prepareArgs = [prepareAssetsScript, releaseAssetsDir];
      const cargoTargetDir = String(process.env.CARGO_TARGET_DIR || "").trim();
      if (cargoTargetDir) {
        prepareArgs.push(
          path.join(path.resolve(repoRoot, cargoTargetDir), "release"),
        );
      }
      await runCommand(process.execPath, prepareArgs);
    }
    const served = await serveDirectory(releaseAssetsDir);
    server = served.server;

    const env = {
      DEEPSEEK_TUI_FORCE_DOWNLOAD: "1",
      DEEPSEEK_TUI_RELEASE_BASE_URL: served.baseUrl,

View on GitHub (pinned to 8880682c63)

Solutions

  1. Point CODEWHALE_SMOKE_ASSETS_DIR at the extracted directory (the output of the prepare-release-assets script)
  2. Unset the variable so the smoke test assembles the assets itself into its temp dir
  3. Extract first: `mkdir -p /tmp/assets && tar -xzf <archive> -C /tmp/assets`, then pass /tmp/assets

Example fix

# before
CODEWHALE_SMOKE_ASSETS_DIR=dist/codewhale-x86_64-unknown-linux-gnu.tar.gz node scripts/release/npm-wrapper-smoke.js

# after
mkdir -p /tmp/assets && tar -xzf dist/codewhale-x86_64-unknown-linux-gnu.tar.gz -C /tmp/assets
CODEWHALE_SMOKE_ASSETS_DIR=/tmp/assets node scripts/release/npm-wrapper-smoke.js
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from 'node:fs';
const dir = process.env.CODEWHALE_SMOKE_ASSETS_DIR;
if (dir && !statSync(dir).isDirectory()) {
  throw new Error(`CODEWHALE_SMOKE_ASSETS_DIR is not a directory: ${dir}`);
}

Prevention

When it happens

Trigger: Setting CODEWHALE_SMOKE_ASSETS_DIR to a .tar.gz/.zip artifact instead of its extracted directory, or to any regular file.

Common situations: CI passing the artifact file path from a previous job step; copying the env var from a context where only the archive exists.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/5fd424e36dd332c4. Report an issue: GitHub.