windmill-labs/windmill · error · Error
${what} must be a non-empty step name without `/` or dot seg
Error message
${what} must be a non-empty step name without `/` or dot segments What it means
assertUsableStepKey validates approval step keys because the key travels as a single URL path segment when getApprovalUrls mints resume/cancel URLs. An empty key, a key containing `/` or `\\`, or a dot segment (`.`/`..`) would produce URLs getApprovalUrls can never address, so the client rejects it up-front with this error naming the offending parameter via `what` (typescript-client/client.ts:1701).
Source
Thrown at typescript-client/client.ts:1701
) => Promise<Jsonified<Awaited<ReturnType<T>>>>;
export interface TaskOptions {
timeout?: number;
tag?: string;
cache_ttl?: number;
priority?: number;
concurrency_limit?: number;
concurrency_key?: string;
concurrency_time_window_s?: number;
}
/** A step key travels as one path segment when its URLs are minted, so it must be
* non-empty and free of `/` and dot segments — otherwise `waitForApproval` would
* accept a key `getApprovalUrls` can never address. */
function assertUsableStepKey(key: string, what: string): void {
const k = key.trim();
if (k === "" || k === "." || k === ".." || key.includes("/") || key.includes("\\")) {
throw new Error(`${what} must be a non-empty step name without \`/\` or dot segments`);
}
}
export let _workflowCtx: WorkflowCtx | null = null;
export function setWorkflowCtx(ctx: WorkflowCtx | null) {
_workflowCtx = ctx;
Reflect.set(globalThis, "__wmill_wf_ctx", ctx);
}
export class WorkflowCtx {
private completed: Record<string, any>;
/** Null-prototype: step keys are caller-supplied, and a plain object would
* resolve `toString`/`constructor`/`__proto__` off `Object.prototype`. */
private counters: Record<string, number> = Object.create(null);
/** Every key handed out by `_allocKey`, so distinct names can't alias one key. */
private _usedKeys = new Set<string>();
private pending: Array<{View on GitHub (pinned to e474e8803c)
Solutions
- Provide a non-empty key of path-segment-safe characters: letters, digits, `-`, `_`.
- Sanitize dynamic keys before passing: strip or replace `/` and `\\`, reject dot-only values.
- Encode hierarchy with a safe separator like `--` instead of `/`.
- Add your own pre-call validation so bad keys fail before reaching the client.
Example fix
// before
await waitForApproval({ key: `approvals/${ticketId}` }); // throws: contains '/'
// after
const key = `approvals--${ticketId}`; // path-segment safe
await waitForApproval({ key }); Defensive patterns
Strategy: validation
Validate before calling
function assertSafeKey(key: string, what = 'step key'): string {
const k = key.trim();
if (k === '' || k === '.' || k === '..' || key.includes('/') || key.includes('\\')) {
throw new Error(`${what} must be a non-empty path-segment-safe name`);
}
return k;
} Type guard
const isUsableStepKey = (k: unknown): k is string =>
typeof k === 'string' && k.trim() !== '' && !k.includes('/') && !k.includes('\\') && k !== '.' && k !== '..'; Try / catch
try {
await waitForApproval({ key });
} catch (e) {
if (e.message.includes('must be a non-empty step name')) {
await waitForApproval({ key: sanitizeKey(key) });
} else throw e;
} Prevention
- Validate keys before passing: no slashes, backslashes, dot segments, or empties.
- Derive keys from safe ids, not user input or file paths.
- Encode hierarchy with a separator like '--' instead of '/'.
When it happens
Trigger: Passing an empty string, `"."`, `".."`, or a key containing slashes/backslashes as the `key` option to waitForApproval, or as a step name wherever assertUsableStepKey runs.
Common situations: Building keys dynamically from user input or file paths (`approvals/2024-05`); interpolating empty template variables into the key; Windows-style backslash separators; copying a step path including slashes into the key field.
Related errors
- {what} must be a non-empty step name without `/` or dot segm
- result.substring(__RESULT_ERR_PREFIX.length)
- App ${appPath} not found
- Invalid migration name '${name}': use only letters, digits,
- Unknown workspace dependencies file format: ${path}. Valid f
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/36af4eb121e442dc.
Report an issue: GitHub.