sinelaw/fresh · error
no API declarations found in
Error message
no API declarations found in {} — start the editor once to write them What it means
When collecting API declaration files from the declarations directory, none could be read, so the client bails telling you to start the editor once — the editor writes the .d.ts-style declaration files on first launch. Without them, script authoring/typechecking has no API surface to work from.
Solutions
- Start the Fresh editor once so it writes its API declaration files, then rerun the command.
- Check you are pointing at the correct declarations directory (the one printed in the message).
- If the editor was started but files are still missing, check editor logs for declaration write failures and fix permissions on the directory.
- Reinstall/repair Fresh if the editor repeatedly fails to emit declarations.
Example fix
# before fresh --script-check myscript.js # declarations never generated # after fresh main.rs # first launch writes API declarations fresh --script-check myscript.js
Defensive patterns
Strategy: fallback
Validate before calling
const fs = require('fs');
const path = require('path');
const dir = path.join(process.env.HOME, '.config/fresh/declarations');
const has = fs.existsSync(dir) && fs.readdirSync(dir).some(f => f.endsWith('.d.ts'));
if (!has) { console.error(`no declarations in ${dir}; start the editor once first`); process.exit(1); } Try / catch
// bash DECL_DIR="$HOME/.config/fresh/declarations" if [ -z "$(ls "$DECL_DIR" 2>/dev/null)" ]; then echo 'starting editor once to generate API declarations...' fresh --headless-generate-declarations || fresh . && sleep 2 fi
Prevention
- Launch the editor once after installing/upgrading Fresh before using script tooling.
- Confirm FRESH_CONFIG/HOME so tooling looks in the same directory the editor writes to.
- Exclude the declarations directory from cleanup scripts.
- Check for write-permission problems if first launch fails to emit declarations.
When it happens
Trigger: Running the declarations-consuming subcommand (e.g. script typecheck/authoring flow) before ever launching the editor, pointing at the wrong declarations directory, or the directory existing but all reads failing.
Common situations: Fresh install where the editor has never run; FRESH_CONFIG/HOME pointing elsewhere so the tool looks in the wrong dir; declarations cleaned by a cleanup script or never written due to an earlier startup failure.
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
- empty script: pass a file, or pipe the source on stdin
- Too many '+ ' arguments (at most one is allowed)
- '+ ' requires a file argument (e.g. 'fresh + file.txt'…
- Cannot open files from multiple remote hosts. First
- Cannot mix local and remote files. Use either local paths…
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/f278be2a18223d6d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/main.rs:4475
}
}
entries
}
/// Where the API declarations live, and their contents.
fn read_api_declarations() -> AnyhowResult<Vec<(String, String)>> {
let dir = fresh::config_io::DirectoryContext::from_system()?
.config_dir
.join("types");
let mut out = Vec::new();
for file in ["fresh.d.ts", "plugins.d.ts"] {
let path = dir.join(file);
if let Ok(text) = std::fs::read_to_string(&path) {
out.push((file.to_string(), text));
}
}
if out.is_empty() {
anyhow::bail!(
"no API declarations found in {} — start the editor once to write them",
dir.display()
);
}
Ok(out)
}
/// `fresh --cmd script api <query>` — find API members by name or description.
///
/// The alternative is grepping a 4000-line declaration file, where a search for
/// "split" returns every unrelated sense of the word. Matching the name first
/// and the prose second puts the verb you meant at the top, and printing each
/// hit with its doc comment means one call usually answers the question
/// outright.
fn script_api(query: &str, flags: &[&str]) -> AnyhowResult<()> {
let json = flags.contains(&"--json");
let needle = query.to_lowercase();
let files = read_api_declarations()?;View on GitHub (pinned to 67894ca546)