windmill-labs/windmill · error · Error
Cannot preview a script metadata file, point to the script c
Error message
Cannot preview a script metadata file, point to the script content file instead (.py, .ts, .go, .sh)
What it means
`wmill script` preview/analysis commands operate on script CONTENT files; passing a script metadata file (.script.json or .script.yaml) is rejected because the metadata alone does not identify the code to preview.
Source
Thrown at cli/src/commands/script/script.ts:1876
filePath = toSyncRootRelativePath(filePath, cwdBeforeConfig);
const remotePath = scriptPathToRemotePath(filePath);
assertRemotePath(remotePath, argPath);
// Same as push: a descriptor-less dbt project's content path is deliberately
// absent, and the project beside it is what says the script is real.
const absentDescriptor = await stat(filePath).then(
() => false,
(e) => isMissingDbtDescriptor(filePath, e)
);
if (!absentDescriptor) {
const fstat = await stat(filePath);
if (!fstat.isFile()) {
throw new Error("file path must refer to a file.");
}
}
if (filePath.endsWith(".script.json") || filePath.endsWith(".script.yaml")) {
throw Error(
"Cannot preview a script metadata file, point to the script content file instead (.py, .ts, .go, .sh)"
);
}
const codebases = await listSyncCodebases(opts);
const language = inferContentTypeFromFilePath(filePath, opts?.defaultTs);
const content = await readScriptContent(filePath);
const input = opts.data ? await resolve(opts.data) : {};
// Read modules from the bundle folder if present. Same suffix and same
// verbatim read as deploy: a dbt project lives in `__dbt/`, and parsing its
// files as scripts would drop the `dbt_project.yml` the executor looks for.
const isFolderLayout = isModuleEntryPoint(filePath);
const isDbt = language === "dbt";
const moduleFolderPath = isFolderLayout
? path.dirname(filePath)
: filePath.substring(0, filePath.indexOf(".")) + getModuleFolderSuffix(language);
const modules = await readModulesFromDisk(View on GitHub (pinned to e474e8803c)
Solutions
- Point the command at the script content file: the sibling .py, .ts, .go or .sh
- Strip the .script.yaml/.script.json extension to derive the content file path
- Filter out *.script.json/*.script.yaml when scripting over a folder
Example fix
// before wmill script analyze f/scripts/my_script.script.yaml // after wmill script analyze f/scripts/my_script.py
Defensive patterns
Strategy: validation
Validate before calling
if (/\.script\.(json|yaml)$/.test(filePath)) throw new Error(`Pass the content file instead of metadata: ${filePath.replace(/\.script\.(json|yaml)$/, '')}`); Type guard
function isScriptMetadata(p: string): boolean { return p.endsWith('.script.json') || p.endsWith('.script.yaml'); } Prevention
- Strip the .script.yaml/.script.json extension to derive the content path before invoking CLI commands
- Filter metadata files out when iterating folders in scripts
- Remember the rule: metadata (.script.json/.script.yaml) pairs with a content file (.py/.ts/.go/.sh)
When it happens
Trigger: Running a preview-style command (around line 1876 of script.ts) with a path ending in .script.json or .script.yaml; the check happens after confirming the path is a file.
Common situations: Tab-completing or pasting the metadata file path instead of the sibling content file; scripting over a directory and iterating all files including metadata.
Related errors
- App ${appPath} not found
- Dependency generation failed: ${queueResponse.status} ${queu
- Failed to poll dependencies job ${jobId}: ${e?.message ?? e}
- No response body for SSE stream
- Datatable '${dtName}' already exists in this workspace
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/ea744dd4e88898b3.
Report an issue: GitHub.