libnyanpasu/clash-nyanpasu · error

no default export or main function

Error message

no default export or main function

What it means

After parsing, wrap_script_if_not_esm looks for either an `export default` statement or a function named `main` to serve as the script entry point. If neither is found, it cannot wrap the script and throws this error.

Source

Thrown at backend/tauri/src/enhance/script/js.rs:396

        visitor.visit_program(&result.program);
        #[cfg(test)]
        eprintln!("visitor: {:#?}", visitor);
        if visitor.default_export.is_some() {
            return Ok(Cow::Borrowed(script));
        }
        // check whether `function main` exists
        match visitor
            .declared_functions
            .iter()
            .find(|(name, _)| name.contains("main"))
        {
            Some((_, span)) => {
                // just insert `export default` before the function
                let mut script = script.to_string();
                script.insert_str(span.start as usize, "export default ");
                Ok(Cow::Owned(script))
            }
            None => Err(anyhow::anyhow!("no default export or main function")),
        }
    }
}

#[cfg(test)]
mod test {
    #[tokio::test]
    async fn yaml_template_preserves_nested_config_through_runner() {
        use super::{super::runner::Runner, JSRunner};

        let runner = JSRunner::try_new().unwrap();
        let input = serde_yaml::from_str("existing: true").unwrap();
        let script = r#"
            import { yaml } from 'nyan:utils';
            export default function main(config) {
                config.a = yaml`nested:
  b: 1
  c: 2

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Add `function main(config) { ... return config; }` to the script.
  2. Or add `export default function main(config) { ... }` for ESM-style scripts.
  3. Rename the entry function to exactly `main` if it exists under another name.

Example fix

// before
function run(config) { return config; }
// after
function main(config) { return run(config); }
Defensive patterns

Strategy: validation

Validate before calling

/(export\s+default|function\s+main\s*\()/.test(scriptSource) || fail('script needs export default or main()')

Try / catch

try {
  await saveScript(src);
} catch (e) {
  if (e.message.includes('no default export or main function')) {
    promptUserToAddMainFunction();
  } else throw e;
}

Prevention

When it happens

Trigger: Submitting an enhancement JS script with no `export default ...` and no top-level `function main(...)` - e.g. only side-effect code or an entry function under a different name.

Common situations: Users write helper-only scripts, name the entry function something other than `main`, or write CommonJS `module.exports` scripts.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/2e59f436c8032b4a. Report an issue: GitHub.