Dokploy/dokploy · error · TRPCError

BAD_REQUEST

BAD_REQUEST

Error message

Invalid file provided

What it means

After the tenant check passes, uploadFileToContainer validates that input.file is a DOM File instance. When the tRPC File input fails to arrive as File (e.g. malformed multipart from a custom client, plain object from a JSON payload, or a Node Buffer), it throws BAD_REQUEST 'Invalid file provided'. This is input-shape validation, not a permissions issue.

Source

Thrown at apps/dokploy/server/api/routers/docker.ts:320

					throw new TRPCError({ code: "UNAUTHORIZED" });
				}
			}
			return await getServiceContainersByAppName(input.appName, input.serverId);
		}),

	uploadFileToContainer: withPermission("docker", "read")
		.input(uploadFileToContainerSchema)
		.mutation(async ({ input, ctx }) => {
			if (input.serverId) {
				const server = await findServerById(input.serverId);
				if (server.organizationId !== ctx.session?.activeOrganizationId) {
					throw new TRPCError({ code: "UNAUTHORIZED" });
				}
			}

			const file = input.file;
			if (!(file instanceof File)) {
				throw new TRPCError({
					code: "BAD_REQUEST",
					message: "Invalid file provided",
				});
			}

			// Convert File to Buffer
			const arrayBuffer = await file.arrayBuffer();
			const fileBuffer = Buffer.from(arrayBuffer);

			await uploadFileToContainer(
				input.containerId,
				fileBuffer,
				file.name,
				input.destinationPath,
				input.serverId || null,
			);

			return { success: true, message: "File uploaded successfully" };

View on GitHub (pinned to 546686ea35)

Solutions

  1. Send the mutation using FormData so the file arrives as a real File instance (dokploy's own client does this)
  2. If calling programmatically, construct a File/Blob: new File([bytes], 'name') and pass it as the file input
  3. Verify no middleware or serialization is converting the File to a plain object

Example fix

// before (fails: plain JSON body)
await trpc.docker.uploadFileToContainer.mutate({
  containerId, path: '/tmp', file: { name: 'a.txt', content: 'hi' }, serverId,
});

// after (File instance)
const file = new File([new Blob(['hi'])], 'a.txt', { type: 'text/plain' });
await trpc.docker.uploadFileToContainer.mutate({
  containerId, path: '/tmp', file, serverId,
});
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof file === 'undefined' || !(file instanceof File)) {
  file = new File([new Blob([data])], filename);
}

Type guard

const isFile = (f: unknown): f is File =>
  typeof File !== 'undefined' && f instanceof File;

Try / catch

try {
  await trpc.docker.uploadFileToContainer.mutate({ ...input, file });
} catch (e) {
  if (e instanceof TRPCClientError && e.message === 'Invalid file provided') {
    // rebuild the file as a real File and retry
  }
}

Prevention

When it happens

Trigger: Calling docker.uploadFileToContainer where input.file is not a File — e.g. sending { file: { name, content } } via JSON, or a client/transport version that does not encode the file as multipart File data.

Common situations: Custom scripts hitting the tRPC endpoint with fetch and forgetting FormData; browser polyfill differences; proxy stripping multipart boundaries.

Understand the failure class

Background: BAD_REQUEST error code: request rejected as invalid (HTTP 400) - causes and fixes across libraries — this error's family across 8 libraries.

Related errors


AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27). Data as JSON: /api/errors/7245c327e3e84c4f. Report an issue: GitHub.