different-ai/openwork · error · Error

Could not upload brand images (${response.status}).

Error message

Could not upload brand images (${response.status}).

What it means

Thrown by handleSave in the brand appearance screen when POST /v1/org/brand-assets (multipart FormData with logo/icon files) returns a non-OK status. getRequestError prefers the server's error message, reauth payload becoming ReauthRequiredError. It means the brand image upload was rejected by the server.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx:248

  async function handleSave(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setPageError(null);
    setPageSuccess(null);

    if (!canManageBrandAppearance) {
      setPageError("Only workspace owners and super-admins can change brand appearance.");
      return;
    }

    try {
      if (logoDraft || iconDraft) {
        setUploadBusy(true);
        await runReauthableAction("upload-brand-assets", async () => {
          const body = new FormData();
          if (logoDraft) body.set("logo", logoDraft.file);
          if (iconDraft) body.set("icon", iconDraft.file);
          const { response, payload } = await requestJson("/v1/org/brand-assets", { method: "POST", body }, 30000);
          if (!response.ok) throw getRequestError(payload, response, `Could not upload brand images (${response.status}).`);
        });
      }

      await updateOrganizationSettings({
        brandAppName: appNameDraft.trim() || null,
        brandAccentColor: accentColorDraft || null,
        ...(logoClearPending ? { brandLogoUrl: null } : {}),
        ...(iconClearPending ? { brandIconUrl: null } : {}),
      });
      setPageSuccess("Brand appearance updated.");
    } catch (error) {
      setPageError(error instanceof Error ? error.message : "Could not update brand appearance.");
    } finally {
      setUploadBusy(false);
    }
  }

  const saveBusy = uploadBusy || mutationBusy === "update-organization-settings";

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Check the surfaced server message for size/format specifics.
  2. Compress or resize the logo/icon and use a supported format (PNG/SVG/JPEG) under the server's size limit.
  3. Retry as an org admin; permissions are required for brand asset writes.
  4. Handle reauth-required errors by re-authenticating.
  5. If 5xx, verify server-side asset storage configuration and logs.

Example fix

// before
if (!response.ok) throw getRequestError(payload, response, `Could not upload brand images (${response.status}).`);
// after
if (!response.ok) {
  const err = getRequestError(payload, response, `Could not upload brand images (${response.status}).`);
  if (response.status === 413) throw new Error("Image too large - please use a file under the size limit.");
  throw err;
}
Defensive patterns

Strategy: validation

Validate before calling

const MAX_BYTES = 5 * 1024 * 1024;
const ALLOWED = ["image/png", "image/jpeg", "image/svg+xml"];
function fileOk(f: File) { return ALLOWED.includes(f.type) && f.size <= MAX_BYTES; }
if ((logoDraft && !fileOk(logoDraft.file)) || (iconDraft && !fileOk(iconDraft.file))) {
  setUploadError("Images must be PNG/JPEG/SVG under 5MB."); return;
}

Type guard

function isImageFile(f: File): boolean { return f.type.startsWith("image/"); }

Try / catch

try {
  await runReauthableAction("upload-brand-assets", upload);
} catch (error) {
  if (isReauthRequiredError(error)) { promptReauth(); return; }
  setUploadError(error instanceof Error ? error.message : "Could not upload brand images.");
}

Prevention

When it happens

Trigger: Upload rejected: file too large (413), unsupported MIME/image format (415/400), user lacks org admin permission (403), session expired (401), reauth required, or storage failure (5xx). 30s timeout applies.

Common situations: Uploading an oversized PNG/SVG logo; uploading a non-image file; non-admin member editing brand settings; self-hosted storage (S3/blob) misconfigured; long upload on slow connection exceeding the 30s timeout then surfacing as error status.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/11e2fb915e63fd43. Report an issue: GitHub.