{"record":{"id":"6382ada2ad289fbb","repo":"windmill-labs/windmill","slug":"project-and-other-deploy-to-the-same-path-s","errorCode":null,"errorMessage":"${project} and ${other} deploy to the same path, so pushing either one replaces the other's script. Keep one: move the dbt project to a path of its own, or remove ${other}.","messagePattern":"(.+?) and (.+?) deploy to the same path, so pushing either one replaces the other's script\\. Keep one: move the dbt project to a path of its own, or remove (.+?)\\.","errorType":"exception","errorClass":"DbtPathCollisionError","httpStatus":null,"severity":"error","filePath":"cli/src/commands/script/script.ts","lineNumber":1187,"sourceCode":"          });\n      })\n    )\n  )\n    .filter((x) => x.file)\n    .map((x) => x.path);\n  // A dbt project's descriptor is OPTIONAL, so `dbt_project.yml` is what says a\n  // dbt script lives at this path — the descriptor is often absent from the\n  // candidates above while the project is perfectly real. Asked BEFORE the\n  // counts below: a project beside an ordinary script is not \"one candidate\",\n  // it is two scripts claiming one remote path, and returning the ordinary one\n  // deploys it OVER the dbt script on the next push of any model.\n  const dbtCandidate = toCandidate(\"__dbt/\" + DBT_DESCRIPTOR_NAME);\n  const dbtProject = await collidingDbtProject(\n    dbtCandidate.slice(0, -(\"__dbt/\" + DBT_DESCRIPTOR_NAME).length),\n  );\n  const nonDbtCandidates = validCandidates.filter((c) => c !== dbtCandidate);\n  if (dbtProject && nonDbtCandidates.length > 0) {\n    throw dbtPathCollisionError(dbtProject, nonDbtCandidates.join(\", \"));\n  }\n  if (validCandidates.length > 1) {\n    throw new UnresolvableScriptContentFileError(\n      `Multiple script files found next to ${filePath}: ${validCandidates.join(\", \")} — ` +\n        `cannot tell which one the metadata belongs to. Keep exactly one.`\n    );\n  }\n  if (validCandidates.length < 1) {\n    // Resolving to the absent descriptor keeps one content path for every\n    // caller; reading it yields an empty descriptor.\n    if (dbtProject) {\n      return dbtCandidate;\n    }\n    throw new UnresolvableScriptContentFileError(\n      `No script file found next to ${filePath} — a script cannot be deployed from its metadata alone. ` +\n        `Add the matching script file (e.g. ${toCandidate(\".ts\")} or ${toCandidate(\n          \".py\"\n        )}) or remove ${filePath}.`","sourceCodeStart":1169,"sourceCodeEnd":1205,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/script/script.ts#L1169-L1205","documentation":"A dbt project folder and an ordinary script file resolve to the same remote script path, so pushing either would overwrite the other's script on the server. The CLI detects the collision (DbtPathCollisionError, a subclass of UnresolvableScriptContentFileError) and refuses to deploy rather than silently replacing a script.","triggerScenarios":"findContentFile finds a dbt_project.yml at a base path AND at least one non-dbt content candidate (e.g. <base>.py or <base>.ts) next to the metadata; both map to the same remote path.","commonSituations":"A dbt project was initialized in a folder that already contained a script file; a script file was added into an existing dbt project folder; git-sync pulls merged both into one directory.","solutions":["Move the dbt project to a path of its own (its own folder not shared with the script file)","Or remove/move the ordinary script file (e.g. the stray .py/.ts) that collides with the dbt project","Re-run the push after only one content source remains at that path"],"exampleFix":"// before\nmyflow/my_script.py\nmyflow/dbt_project.yml   # both deploy to myflow\n// after\nmyflow/my_script.py\nmyflow_dbt/dbt_project.yml  # separate path","handlingStrategy":"validation","validationCode":"import { stat } from 'deno/fs'; const hasDbt = await stat(`${base}/dbt_project.yml`).then(() => true).catch(() => false); const stray = ['.py','.ts','.go','.sh'].filter(async ext => await stat(base.replace(/\\.script\\.(yaml|json|lock)$/, ext)).then(s => s.isFile).catch(() => false)); if (hasDbt && stray.length) throw new Error(`dbt project and ${stray} share one path`);","typeGuard":"import { DbtPathCollisionError } from './script.ts'; function isDbtCollision(e: unknown): e is DbtPathCollisionError { return e instanceof DbtPathCollisionError; }","tryCatchPattern":"try { await pushAll(); } catch (e) { if (isDbtCollision(e)) { console.error(`Fix the path collision locally: ${e.message}`); Deno.exit(1); } throw e; }","preventionTips":["Never mix a dbt project folder and script files under one base path","Layout rule: one content source (script OR dbt project) per deploy path","Add a repo lint that flags dbt_project.yml with sibling script content files"],"tags":["dbt","path-collision","cli","deploy"],"backgroundTag":"path-collision","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}