{"record":{"id":"fae7a99ba7fb2977","repo":"windmill-labs/windmill","slug":"warning-workspace-name-workspacename-contain","errorCode":null,"errorMessage":"Warning: Workspace name \"${workspaceName}\" contains filesystem-unsafe characters (/ \\ : * ? \" < > | .) and was sanitized to \"${sanitizedName}\". This may cause collisions with other similarly named branches.","messagePattern":"Warning: Workspace name \"(.+?)\" contains filesystem-unsafe characters \\(/ \\\\ : \\* \\? \" < > \\| \\.\\) and was sanitized to \"(.+?)\"\\. This may cause collisions with other similarly named branches\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli/src/core/specific_items.ts","lineNumber":304,"sourceCode":"    if (basePathMatch && specificItems.resources) {\n      const basePath = basePathMatch[1] + '.resource.yaml';\n      return matchesPatterns(basePath, specificItems.resources);\n    }\n  }\n\n  return false;\n}\n\n/**\n * Convert a base path to a workspace-specific path\n */\nexport function toWorkspaceSpecificPath(basePath: string, workspaceName: string): string {\n  // Sanitize branch name to be filesystem-safe\n  const sanitizedName = workspaceName.replace(/[\\/\\\\:*?\"<>|.]/g, '_');\n\n  // Warn about potential collisions if sanitization occurred\n  if (sanitizedName !== workspaceName) {\n    console.warn(`Warning: Workspace name \"${workspaceName}\" contains filesystem-unsafe characters (/ \\\\ : * ? \" < > | .) and was sanitized to \"${sanitizedName}\". This may cause collisions with other similarly named branches.`);\n  }\n\n  // Check for folder meta file pattern: folder.meta.{yaml,json} -> folder.workspaceName.meta.{yaml,json}\n  const folderMetaMatch = basePath.match(/^(.*)\\/folder\\.meta\\.(yaml|json)$/);\n  if (folderMetaMatch) {\n    return `${folderMetaMatch[1]}/folder.${sanitizedName}.meta.${folderMetaMatch[2]}`;\n  }\n\n  // Check for settings.{yaml,json}: settings.{ext} -> settings.workspaceName.{ext}\n  const settingsMatch = basePath.match(/^settings\\.(yaml|json)$/);\n  if (settingsMatch) {\n    return `settings.${sanitizedName}.${settingsMatch[1]}`;\n  }\n\n  // Check for resource file pattern (e.g., .resource.file.ini)\n  const resourceFileMatch = basePath.match(/^(.+?)(\\.resource\\.file\\..+)$/);\n\n  let extension: string;","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/core/specific_items.ts#L286-L322","documentation":"toWorkspaceSpecificPath builds branch/workspace-specific sync paths by sanitizing the workspace name: characters / \\ : * ? \" < > | . are replaced with underscores. If the name contained any of those characters (i.e. sanitization changed it), a console.warn explains the rename and that it can collide with other similarly named workspaces. It is informational — sync continues with the sanitized path — but two workspaces like feature/x and feature_x will map to the same directory and clobber each other's files.","triggerScenarios":"Calling toWorkspaceSpecificPath (directly, or via getWorkspaceSpecificPath / branchSpecific / findFilesetResourceFile during sync pull/push) with a workspaceName containing any of / \\ : * ? \" < > | . — most commonly Git branch names with slashes like feature/add-login.","commonSituations":"Using a Git branch name as the workspace name in a branch-deployed sync flow (feature/xyz becomes feature_xyz); Windows-incompatible names; names containing dots from semver-like tags (v1.2.3 becomes v1_2_3); two branches `a/b` and `a_b` silently sharing one directory.","solutions":["Rename the workspace/branch to contain only filesystem-safe characters (letters, digits, -, _).","If the branch name must contain slashes, accept the sanitized path but ensure no other branch sanitizes to the same string.","Set the workspace name explicitly in CI to a pre-sanitized value (e.g. replace '/' with '-' before invoking wmill).","Verify which directory files are being read from/written to after the warning and update scripts/docs accordingly."],"exampleFix":"// before (CI)\nBRANCH=\"${GITHUB_REF#refs/heads/}\"   # feature/add-login\nwmill sync push --workspace-name \"$BRANCH\"\n\n// after\nBRANCH=$(echo \"${GITHUB_REF#refs/heads/}\" | tr '/' '-')\nwmill sync push --workspace-name \"$BRANCH\"","handlingStrategy":"validation","validationCode":"const UNSAFE = /[/\\\\:*?\"<>|.]/;\nif (UNSAFE.test(workspaceName)) {\n  throw new Error(`workspace name '${workspaceName}' contains filesystem-unsafe characters; sanitize it before syncing`);\n}","typeGuard":"function isFilesystemSafeName(name: string): boolean {\n  return /^[A-Za-z0-9_-]+$/.test(name);\n}","tryCatchPattern":"const safeName = workspaceName.replace(/[/\\\\:*?\"<>|.]/g, \"-\");\nconsole.log(`syncing as workspace '${safeName}'`);\nawait $`wmill sync push --workspace-name ${safeName}`;","preventionTips":["Pre-sanitize Git branch names in CI (replace / with -) before using them as workspace names","Restrict workspace names to [A-Za-z0-9_-] when creating them","Avoid dots in names (v1.2.3 -> v1_2_3 collisions)","Keep a mapping of branch -> sanitized name if you cannot rename branches"],"tags":["cli","filesystem","path-sanitization","branch-deploys","naming-collision"],"backgroundTag":"unsafe-path-characters","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"}