zellij-org/zellij · error

only relative sibling module specifiers are supported, found

Error message

only relative sibling module specifiers are supported, found '{}' at {}

What it means

Module specifiers must be exactly `./name.js` — starting with `./` and ending with `.js` — so the flattener can map the import to a bundled sibling module. Bare names, parent paths, package specifiers, URLs, or extension-less paths are rejected.

Source

Thrown at xtask/src/assets.rs:240

        .trim_end_matches(',')
        .chars()
        .all(|c| c.is_alphanumeric() || c == '_' || c == '$' || c == ' ')
}

fn validate_module_specifier(line: &str, location: &str) -> anyhow::Result<()> {
    let specifier = line
        .rsplit_once(" from ")
        .map(|(_, specifier)| specifier)
        .ok_or_else(|| anyhow!("missing module specifier at {}", location))?
        .trim()
        .trim_end_matches(';')
        .trim_matches(|c| c == '"' || c == '\'');

    let name = specifier
        .strip_prefix("./")
        .and_then(|name| name.strip_suffix(".js"))
        .ok_or_else(|| {
            anyhow!(
                "only relative sibling module specifiers are supported, found '{}' at {}",
                specifier,
                location
            )
        })?;

    if !MODULE_ORDER.contains(&name) {
        return Err(anyhow!(
            "module '{}' referenced at {} is not part of the bundle",
            name,
            location
        ));
    }
    Ok(())
}

fn top_level_declarations(chunk: &str) -> Vec<String> {
    let mut names = Vec::new();

View on GitHub (pinned to 98a0837077)

Solutions

  1. Rewrite the specifier as './name.js' (keep the leading ./ and the .js suffix)
  2. Vendor any npm dependency into a local sibling module file and import it relatively
  3. Compare the exact specifier string quoted in the error against the ./x.js form

Example fix

// before (rejected)
import { debounce } from 'utils';

// after
import { debounce } from './utils.js';
Defensive patterns

Strategy: validation

Validate before calling

# specifiers must look like ./name.js
for spec in $(grep -hoE "from ['\"][^'\"]+['\"]" zellij-client/assets/*.js | sed -E "s/from ['\"]([^'\"]+)['\"]/\1/"); do
  case "$spec" in
    ./*.js) ;;
    *) echo "unsupported specifier: $spec (expected ./name.js)"; exit 1;;
  esac
done

Type guard

fn is_relative_sibling_specifier(specifier: &str) -> bool {
    specifier.strip_prefix("./").is_some_and(|s| s.ends_with(".js"))
}

Prevention

When it happens

Trigger: `import { x } from 'utils.js';` (missing ./), `from '../lib/x.js'`, `from 'lodash'`, `from './utils'` (missing .js).

Common situations: Editor auto-import inserting bare or extension-less specifiers; copying code from bundler-based projects (webpack/vite) where extensions are omitted; muscle memory from npm imports.

Related errors


AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16). Data as JSON: /api/errors/d8d2acc9dc688277. Report an issue: GitHub.