windmill-labs/windmill · error
no target folder
Error message
no target folder
What it means
runBulk's 'move' action requires opts.target (the destination folder path). It throws synchronously per item when target is missing, since moving without a destination is a caller bug, not an item failure.
Source
Thrown at frontend/src/lib/components/home/bulkActions.ts:145
export type BulkOutcome = { item: BulkItem; error?: string }
/**
* Apply `action` to each item in turn, never aborting the batch on a failure —
* every item gets its own outcome so partial success is reported rather than
* hidden. `onProgress` is called after each item with the number completed.
*/
export async function runBulk(
action: BulkAction,
items: BulkItem[],
ctx: BulkContext,
opts: { target?: string; onProgress?: (done: number) => void } = {}
): Promise<BulkOutcome[]> {
const outcomes: BulkOutcome[] = []
for (const item of items) {
try {
switch (action) {
case 'move':
if (!opts.target) throw new Error('no target folder')
await moveItem(ctx, item, opts.target)
break
case 'archive':
await setArchived(ctx, item, true)
break
case 'unarchive':
await setArchived(ctx, item, false)
break
case 'delete':
await deleteItem(ctx, item)
break
case 'discard':
await discardItemDraft(ctx, item)
break
}
outcomes.push({ item })
} catch (e: any) {
outcomes.push({ item, error: e?.body ?? e?.message ?? String(e) })View on GitHub (pinned to e474e8803c)
Solutions
- Pass opts.target, e.g. runBulk(ctx, 'move', items, { workspace, target: 'folder/sub' }).
- Disable the Move button in the UI until a folder is selected.
- Guard in the caller: if (!target) return before invoking runBulk.
- Use a folder picker component that cannot resolve to an empty path.
Example fix
// before
await runBulk(ctx, 'move', items, { workspace })
// after
await runBulk(ctx, 'move', items, { workspace, target: selectedFolder }) Defensive patterns
Strategy: validation
Validate before calling
if (action === 'move' && !opts?.target) throw new Error('Select a destination folder first') Type guard
function hasTarget(o) { return typeof o?.target === 'string' && o.target.length > 0 } Try / catch
try { await runBulk(ctx, 'move', items, opts) } catch (e) { if (e.message === 'no target folder') openFolderPicker(); else throw e } Prevention
- Disable the Move action until a folder is selected in the picker
- Always pass an explicit { target } when calling runBulk programmatically
- Validate opts before entering the bulk loop
When it happens
Trigger: Calling runBulk('move', items, opts) with opts.target undefined/null — e.g. the UI move dialog was dismissed or the folder picker returned nothing.
Common situations: Button wired to 'move' before the user selected a destination folder; programmatic use passing only { workspace }; target cleared by form reset.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- --kind is required. Valid kinds: ${TRIGGER_TYPES.join(", ")}
- Table name is required
- Table name is required
- inlineScript is required when runnable type is "inline".
- path is required when runnable type is "script", "flow", or
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/6c774066b8ce9ffa.
Report an issue: GitHub.