paperclipai/paperclip · error
Select a company to upload images
Error message
Select a company to upload images
What it means
The image-upload mutation in AgentDetail requires an active company selection because assets are uploaded to a company-scoped assets API endpoint. If the user has not selected a company (selectedCompanyId is null/undefined), the mutation throws this error instead of calling assetsApi.uploadImage. It is a guard against an impossible/ambiguous request rather than an API failure.
Source
Thrown at ui/src/pages/AgentDetail.production.tsx:2434
},
onError: () => setAwaitingRefresh(false),
});
const deleteFile = useMutation({
mutationFn: (relativePath: string) => agentsApi.deleteInstructionsFile(agent.id, relativePath, companyId),
onMutate: () => setAwaitingRefresh(true),
onSuccess: (_, relativePath) => {
queryClient.invalidateQueries({ queryKey: queryKeys.agents.instructionsBundle(agent.id) });
queryClient.removeQueries({ queryKey: queryKeys.agents.instructionsFile(agent.id, relativePath) });
queryClient.invalidateQueries({ queryKey: queryKeys.agents.detail(agent.id) });
queryClient.invalidateQueries({ queryKey: queryKeys.agents.detail(agent.urlKey) });
},
onError: () => setAwaitingRefresh(false),
});
const uploadMarkdownImage = useMutation({
mutationFn: async ({ file, namespace }: { file: File; namespace: string }) => {
if (!selectedCompanyId) throw new Error("Select a company to upload images");
return assetsApi.uploadImage(selectedCompanyId, file, namespace);
},
});
useEffect(() => {
if (!bundle) return;
if (!bundleMatchesDraft) {
if (selectedFile !== currentEntryFile) setSelectedFile(currentEntryFile);
return;
}
const availablePaths = bundle.files.map((file) => file.path);
if (availablePaths.length === 0) {
if (selectedFile !== bundle.entryFile) setSelectedFile(bundle.entryFile);
return;
}
if (!availablePaths.includes(selectedFile) && selectedFile !== currentEntryFile && !pendingFiles.includes(selectedFile)) {
setSelectedFile(availablePaths.includes(bundle.entryFile) ? bundle.entryFile : availablePaths[0]!);
}View on GitHub (pinned to 01ad858492)
Solutions
- Select a company in the company picker before uploading/pasting images.
- Gate the upload affordance (paste/drop handler, toolbar button) on Boolean(selectedCompanyId) so it is disabled without a company.
- Ensure the company selection context is hydrated before rendering the editor.
- If the page is inherently company-scoped, redirect to company selection when selectedCompanyId is missing.
Example fix
// before
if (!selectedCompanyId) throw new Error("Select a company to upload images");
return assetsApi.uploadImage(selectedCompanyId, file, namespace);
// after (caller-side guard)
if (!selectedCompanyId) {
toast.info("Select a company to upload images");
return;
}
await uploadMarkdownImage.mutateAsync({ file, namespace }); Defensive patterns
Strategy: validation
Validate before calling
if (!selectedCompanyId) {
toast.info("Select a company to upload images");
return;
} Type guard
const canUpload = (id: string | null | undefined): id is string => typeof id === "string" && id.length > 0;
Try / catch
try {
await uploadMarkdownImage.mutateAsync({ file, namespace });
} catch (e) {
if (e.message === "Select a company to upload images") toast.info(e.message);
else toast.error("Image upload failed");
} Prevention
- Disable paste/drop image handling and upload buttons until a company is selected.
- Block editor interactions behind a company-selected gate on company-scoped pages.
- Show the company picker prominently and persist the last selection.
When it happens
Trigger: Invoking uploadMarkdownImage.mutate({ file, namespace }) (e.g. pasting or dropping an image into the markdown editor) while no company is selected in the company selector.
Common situations: Landing on the agent detail page before the company context loads; the company selector was never set; a deep link that bypasses company selection; company data still fetching so the id is briefly null when the user pastes an image.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Select an organization to test adapter environment
- Select a company to create secrets
- Select a skill first.
- [adapter-ui-loader] Failed to load UI parser for "${adapterT
- Unable to resolve company for plugin API route
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/8b6ac07196fd2383.
Report an issue: GitHub.