wavetermdev/waveterm · error

Copy failed:

Error message

Copy failed:

What it means

DirectoryPreview's handleDropCopy invokes the FileCopyCommand RPC for a drop/copy operation; on rejection it logs 'Copy failed:' with the error. If the error indicates an overwrite/merge conflict (overwriteError/mergeError), the UI offers a retry with overwrite/merge options instead of failing outright.

Source

Thrown at frontend/app/view/preview/preview-directory.tsx:719

    }, [filteredData]);

    const entryManagerPropsAtom = useState(
        atom<EntryManagerOverlayProps>(null) as PrimitiveAtom<EntryManagerOverlayProps>
    )[0];
    const [entryManagerProps, setEntryManagerProps] = useAtom(entryManagerPropsAtom);

    const { refs, floatingStyles, context } = useFloating({
        open: !!entryManagerProps,
        onOpenChange: () => setEntryManagerProps(undefined),
        middleware: [offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)],
    });

    const handleDropCopy = useCallback(
        async (data: CommandFileCopyData, isDir: boolean) => {
            try {
                await env.rpc.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
            } catch (e) {
                console.warn("Copy failed:", e);
                const copyError = `${e}`;
                const allowRetry = copyError.includes(overwriteError) || copyError.includes(mergeError);
                let errorMsg: ErrorMsg;
                if (allowRetry) {
                    errorMsg = {
                        status: "Confirm Overwrite File(s)",
                        text: "This copy operation will overwrite an existing file. Would you like to continue?",
                        level: "warning",
                        buttons: [
                            {
                                text: "Delete Then Copy",
                                onClick: async () => {
                                    data.opts.overwrite = true;
                                    await handleDropCopy(data, isDir);
                                },
                            },
                            {
                                text: "Sync",

View on GitHub (pinned to a4447c1563)

Solutions

  1. If the UI shows 'Confirm Overwrite File(s)', accept to retry with overwrite/merge flags
  2. Increase the copy timeout (data.opts.timeout) for large copies and retry
  3. Verify source files exist and the destination has write permission
  4. Refresh the preview and retry the copy

Example fix

// before
await env.rpc.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
// after
try {
    await env.rpc.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
} catch (e) {
    if (`${e}`.includes(overwriteError)) {
        await env.rpc.FileCopyCommand(TabRpcClient, { ...data, opts: { ...data.opts, overwrite: true } }, { timeout: data.opts.timeout });
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before copying, detect conflicts client-side when possible
const conflict = await destExists(data) && !data.opts.overwrite && !data.opts.merge;
if (conflict) {
    setErrorMsg({ status: 'Confirm Overwrite File(s)', text: 'Destination exists. Overwrite?', level: 'warning' });
    return;
}

Type guard

function isRetryableCopyConflict(copyError: string, overwriteError: string, mergeError: string): boolean {
    return copyError.includes(overwriteError) || copyError.includes(mergeError);
}

Try / catch

try {
    await env.rpc.FileCopyCommand(TabRpcClient, data, { timeout: data.opts.timeout });
} catch (e) {
    console.warn('Copy failed:', e);
    const copyError = `${e}`;
    if (copyError.includes(overwriteError) || copyError.includes(mergeError)) {
        setErrorMsg({ status: 'Confirm Overwrite File(s)', text: copyError, level: 'warning' }); // offer retry with overwrite/merge
    } else {
        setErrorMsg({ status: 'Copy Failed', text: copyError });
    }
}

Prevention

When it happens

Trigger: FileCopyCommand rejects (timeout or backend error): destination file exists without overwrite permission, source missing, permission denied, or the configured copy timeout elapses for large copies.

Common situations: Copying onto existing files without overwrite consent; copying large trees that exceed data.opts.timeout; copying to a read-only or full destination; dragging from a source that changed between drag start and drop.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/d5e0492883470627. Report an issue: GitHub.