swc-project/swc · error · ReferenceError

Duplicated methods ( ) can't be decorated.

Error message

Duplicated methods (${element.key}) can't be decorated.

What it means

The napi `parseFileSync(path, opts)` function loads the JS/TS file from disk via SourceMap::load_file and unwraps it with .expect("failed to read program file"). Any I/O failure - missing path, permission denied, or content the loader cannot handle - becomes a Rust panic that napi-rs reports to JS as an exception with this message. Unlike parse errors, nothing is captured by the swc handler because the panic happens before parsing starts.

Solutions

  1. Verify the path before calling: use fs.existsSync / fs.statSync and resolve it to an absolute path with path.resolve.
  2. Check file readability (fs.accessSync(p, fs.constants.R_OK)) and fix permissions if needed.
  3. Prefer the buffer-based parse API (parseSync with source text) when you already have the contents in memory, avoiding filesystem coupling entirely.
  4. Wrap the call in try/catch and surface the JS exception message - it contains the path context from the panic.

Example fix

// before: panics inside Rust when the file is missing
const out = parseFileSync('src/app.ts', opts);

// after: validate first, then call
const file = path.resolve('src/app.ts');
fs.accessSync(file, fs.constants.R_OK);
const out = parseFileSync(file, opts);
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';

function parseFileSyncSafe(relPath, opts) {
  const file = path.resolve(relPath); // cwd-independent
  const st = fs.statSync(file); // throws ENOENT/EACCES with a clear JS error
  if (!st.isFile()) throw new Error(`not a file: ${file}`);
  fs.accessSync(file, fs.constants.R_OK);
  return parseFileSync(file, opts);
}

Type guard

function isReadableFile(p: string): boolean {
  try {
    return fs.statSync(p).isFile();
  } catch {
    return false;
  }
}

Try / catch

try {
  result = parseFileSync(file, opts);
} catch (e) {
  if (/failed to read program file/.test(String(e?.message))) {
    throw new Error(`swc could not read ${file}: check the path and permissions`, { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parseFileSync('src/foo.ts', opts) where the file does not exist, is a directory, has no read permission, or the path is relative to a different working directory than assumed (the Rust side resolves it from the process cwd).

Common situations: Bundlers or CLIs run from a different cwd so a relative path resolves wrong; globs that include deleted files; permission-restricted mount or Docker volume without read access; case-sensitive filesystem mismatches after cloning a repo from Windows.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/ac14707147b447d5. Report an issue: GitHub.

Appendix: source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs:56

}
function _coalesceGetterSetter(element, other) {
    if (element.descriptor.get !== undefined) other.descriptor.get = element.descriptor.get;
    else other.descriptor.set = element.descriptor.set;
}
function _coalesceClassElements(elements) {
    var newElements = [];
    var isSameElement = function isSameElement(other) {
        return other.kind === "method" && other.key === element.key && other.placement === element.placement;
    };

    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];
        var other;

        if (element.kind === "method" && (other = newElements.find(isSameElement))) {
            if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) {
                if (_hasDecorators(element) || _hasDecorators(other)) {
                    throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated.");
                }
                other.descriptor = element.descriptor;
            } else {
                if (_hasDecorators(element)) {
                    if (_hasDecorators(other)) {
                        throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ").");
                    }
                    other.decorators = element.decorators;
                }
                _coalesceGetterSetter(element, other);
            }
        } else {
            newElements.push(element);
        }
    }

    return newElements;
}

View on GitHub (pinned to 5176682b65)