different-ai/openwork · warning · Error
Desktop policies require an Enterprise plan
Error message
Desktop policies require an Enterprise plan
What it means
createDesktopPolicy POSTs a new policy to /v1/desktop-policies. When the Den server answers 402 Payment Required, the client deliberately maps it to the constant DESKTOP_POLICY_ENTERPRISE_PLAN_ERROR ("Desktop policies require an Enterprise plan") instead of the generic request-error fallback. This is a plan-gating signal: the org's subscription tier does not include desktop policy management.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/desktop-policy-data.tsx:200
setBusy(false);
}
}
useEffect(() => {
void reloadPolicies();
}, [orgId]);
return { definitions, desktopPolicies, busy, error, reloadPolicies };
}
export async function createDesktopPolicy(input: DesktopPolicyPayload) {
const { response, payload } = await requestJson("/v1/desktop-policies", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(input),
}, 12000);
if (!response.ok) {
if (response.status === 402) throw new Error(DESKTOP_POLICY_ENTERPRISE_PLAN_ERROR);
throw getRequestError(payload, response, `Failed to create desktop policy (${response.status}).`);
}
}
export async function updateDesktopPolicy(policyId: string, input: DesktopPolicyPayload) {
const { response, payload } = await requestJson(`/v1/desktop-policies/${encodeURIComponent(policyId)}`, {
method: "PATCH",
headers: { "content-type": "application/json" },
body: JSON.stringify(input),
}, 12000);
if (!response.ok) {
if (response.status === 402) throw new Error(DESKTOP_POLICY_ENTERPRISE_PLAN_ERROR);
throw getRequestError(payload, response, `Failed to update desktop policy (${response.status}).`);
}
}
export async function deleteDesktopPolicy(policyId: string) {
const { response, payload } = await requestJson(`/v1/desktop-policies/${encodeURIComponent(policyId)}`, {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Upgrade the organization to an Enterprise plan in Den/billing, then retry creating the policy.
- Verify the current subscription status on the org's billing page (a lapsed subscription can also return 402).
- If self-hosting, apply the Enterprise license/entitlement to the Den instance.
- If you believe the org is already Enterprise, confirm the correct org/workspace is selected — the 402 is scoped to the authenticated org.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!orgPlan.includes("enterprise")) {
showUpgradePrompt("Desktop policies require an Enterprise plan");
return; // skip createDesktopPolicy
} Type guard
function isPlanGatedError(e: unknown): e is Error {
return e instanceof Error && e.message === "Desktop policies require an Enterprise plan";
} Try / catch
try {
await createDesktopPolicy(input);
} catch (e) {
if (isPlanGatedError(e)) showUpgradePrompt(e.message);
else showError(e instanceof Error ? e.message : "Failed to create desktop policy.");
} Prevention
- Check the org's plan/entitlements before rendering the policy editor so the 402 path is rarely hit.
- Cache the org plan in app state and refresh it after any billing change.
- Surface an upgrade CTA instead of a generic error when the message matches the plan gate.
- Verify subscription is active (not past-due) after billing operations.
When it happens
Trigger: Calling createDesktopPolicy (via handleSave on the policy editor or ensureAdminExceptionPolicy) while the org is on a non-Enterprise plan and Den returns HTTP 402 for POST /v1/desktop-policies.
Common situations: A trial or free/Pro org tries to create its first desktop policy; billing lapsed and the subscription downgraded; a self-hosted instance whose license doesn't cover the desktop-policy feature.
Related errors
- request_failed
- invalid_payload
- Failed to load desktop policies (${response.status}).
- Could not load egress diagnostics (${response.status}).
- Egress diagnostic could not start (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/5515d219ae6ba57c.
Report an issue: GitHub.