different-ai/openwork · error
A valid transferId is required.
Error message
A valid transferId is required.
What it means
desktopTransferKey() validates the transferId supplied by a renderer over IPC before keying an active-transfer map. A valid id must be a non-empty string of at most 128 chars matching /^[a-zA-Z0-9._-]+$/. Anything else throws this error, protecting the Map from untrusted or malformed renderer input.
Source
Thrown at apps/desktop/electron/main.mjs:1078
const browserPanel = createBrowserPanel({
remoteDebugPort,
getWindow: () => mainWindow,
onDeepLink: (urls) => queueDeepLinks(urls),
});
const workspaceStore = createWorkspaceStore({
app,
defaultDenBaseUrl: DEFAULT_DEN_BASE_URL,
defaultRequireSignin: DEFAULT_DESKTOP_REQUIRE_SIGNIN,
forceRequireSignin: FORCE_DESKTOP_REQUIRE_SIGNIN,
});
const activeDesktopTransfers = new Map();
function desktopTransferKey(event, transferId) {
const normalizedId = typeof transferId === "string" ? transferId.trim() : "";
if (!normalizedId || normalizedId.length > 128 || !/^[a-zA-Z0-9._-]+$/.test(normalizedId)) {
throw new Error("A valid transferId is required.");
}
return `${event.sender.id}:${normalizedId}`;
}
async function runDesktopTransfer(event, input, operation) {
const key = desktopTransferKey(event, input?.transferId);
if (activeDesktopTransfers.has(key)) throw new Error("transferId is already active.");
const controller = new AbortController();
const abort = () => controller.abort();
activeDesktopTransfers.set(key, controller);
event.sender.once("destroyed", abort);
try {
// Both authorities come from app-owned state in userData; workspace-
// writable configuration must never widen where a transfer may write.
const [authorizedRoots, allowedUrlPrefixes] = await Promise.all([
workspaceStore.listLocalWorkspacePaths(),
workspaceStore.listRemoteWorkspaceUrlPrefixes(),
]);View on GitHub (pinned to 2b7df46e8a)
Solutions
- Generate transferId in the renderer as crypto.randomUUID() (matches the allowed charset).
- Trim and validate the id client-side before invoking the IPC call.
- Ensure input is an object: pass { transferId } rather than the raw string.
- Check for version skew — reload/rebuild the renderer so it matches the main-process contract.
Example fix
// before
invoke('desktop:transfer', { transferId: `${file.name} (${i})` });
// after
const transferId = crypto.randomUUID();
invoke('desktop:transfer', { transferId }); Defensive patterns
Strategy: validation
Validate before calling
const TRANSFER_ID_RE = /^[a-zA-Z0-9._-]{1,128}$/;
if (typeof transferId !== 'string' || !TRANSFER_ID_RE.test(transferId.trim())) {
throw new TypeError('transferId must be 1-128 chars of [a-zA-Z0-9._-]');
} Type guard
function isValidTransferId(v) {
return typeof v === 'string' && v.length > 0 && v.length <= 128 && /^[a-zA-Z0-9._-]+$/.test(v);
} Try / catch
try {
await runDesktopTransfer(event, input, op);
} catch (err) {
if (String(err.message) === 'A valid transferId is required.') {
console.error('Bad transferId from renderer:', input?.transferId);
} else throw err;
} Prevention
- Generate ids with crypto.randomUUID().
- Validate the id in the renderer before invoking IPC.
- Never interpolate user/file names into transferId.
- Mirror the main-process regex in renderer-side shared validation code.
When it happens
Trigger: Any IPC desktop transfer call (runDesktopTransfer) whose input.transferId is missing, not a string, empty/whitespace, longer than 128 chars, or contains characters outside [a-zA-Z0-9._-] (e.g. spaces, slashes, unicode).
Common situations: Renderer sending undefined transferId after a refactor; generating ids with characters like ':' or '/'; pasting a UUID with braces; corrupted IPC payload from an older renderer bundle.
Related errors
- transferId is already active.
- Desktop integration is disabled for test profiles.
- Could not start OpenWork UI control bridge.
- Agent context diagnostics timeout must be between 1 ms and 3
- Electron desktop helper is unavailable: ${command}
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/f0653843265f98ae.
Report an issue: GitHub.