different-ai/openwork · error · DenApiError
invalid_marketplace_payload
invalid_marketplace_payload
Error message
Marketplace response was missing plugin details.
What it means
DenApiError thrown by getOrgMarketplaceResolved in apps/app/src/app/lib/den.ts when GET /v1/marketplaces/{marketplaceId}/resolved returned 2xx but getOrgMarketplaceResolved could not extract the resolved marketplace with its plugin details from the payload. It guards callers against a marketplace object missing plugins/components or being structurally wrong.
Source
Thrown at apps/app/src/app/lib/den.ts:3450
async listMeLibraryPlugins(orgId: string): Promise<DenMeLibraryPlugin[]> {
const payload = await requestJson<unknown>(
baseUrls,
"/v1/me/library",
{ method: "GET", token, organizationId: orgId },
);
return getMeLibraryPlugins(payload);
},
async getOrgMarketplaceResolved(orgId: string, marketplaceId: string): Promise<DenOrgMarketplaceResolved> {
const payload = await requestJson<unknown>(
baseUrls,
`/v1/marketplaces/${encodeURIComponent(marketplaceId)}/resolved`,
{ method: "GET", token, organizationId: orgId },
);
const resolved = getOrgMarketplaceResolved(payload);
if (!resolved) {
throw new DenApiError(500, "invalid_marketplace_payload", "Marketplace response was missing plugin details.");
}
return resolved;
},
async getOrgPluginResolved(orgId: string, plugin: DenOrgPlugin): Promise<DenOrgPluginResolved> {
const payload = await requestJson<unknown>(
baseUrls,
`/v1/plugins/${encodeURIComponent(plugin.id)}/resolved`,
{ method: "GET", token, organizationId: orgId },
);
return getOrgPluginResolved(plugin, payload);
},
async createOrgPlugin(
orgId: string,
input: {
name: string;
description?: string | null;View on GitHub (pinned to 2b7df46e8a)
Solutions
- Inspect the raw JSON from /v1/marketplaces/:id/resolved and compare with the fields getOrgMarketplaceResolved expects
- Verify the marketplaceId belongs to the org and has published plugins (check via /v1/marketplaces?status=active)
- Align server and client versions — a resolved-schema drift means upgrade one side
- Bypass any caching proxy to rule out a stale/mangled cached body
- Re-fetch after re-authenticating if the response could be a limited-permission stub
Example fix
// before
const resolved = getOrgMarketplaceResolved(payload);
if (!resolved) {
throw new DenApiError(500, "invalid_marketplace_payload", "Marketplace response was missing plugin details.");
}
// after
caller-side guard:
try {
const resolved = await client.getOrgMarketplaceResolved(orgId, marketplaceId);
} catch (err) {
if (err instanceof DenApiError && err.code === "invalid_marketplace_payload") {
// fall back to listOrgMarketplaces to verify the marketplace id/state
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// pre-check the marketplace exists and is active
const marketplaces = await client.listOrgMarketplaces(orgId);
if (!marketplaces.some((m) => m.id === marketplaceId)) {
throw new Error(`Marketplace not found or inactive: ${marketplaceId}`);
} Type guard
function isResolvedMarketplace(v: unknown): v is DenOrgMarketplaceResolved {
return (
typeof v === "object" && v !== null &&
"id" in v && "plugins" in v && Array.isArray((v as { plugins?: unknown }).plugins)
);
} Try / catch
try {
const resolved = await client.getOrgMarketplaceResolved(orgId, marketplaceId);
} catch (err) {
if (err instanceof DenApiError && err.code === "invalid_marketplace_payload") {
// fall back to listOrgMarketplaces or show an empty marketplace state
} else { throw err; }
} Prevention
- Verify marketplaceId against listOrgMarketplaces before calling /resolved
- Keep Den server and client schema definitions in sync
- Treat an empty/unpublished marketplace as an expected state in the UI
- Bypass caches when debugging marketplace responses
- Validate the parsed result with a type guard before rendering plugin details
When it happens
Trigger: The /resolved endpoint responds 200 with null/empty data (marketplace empty or unpublished), the body lacks the plugin detail fields the parser requires, or the server's resolved-marketplace schema differs from what this client version expects.
Common situations: Self-hosted Den server running an older schema for /v1/marketplaces/:id/resolved; a marketplace that exists but has no published plugins yet; wrong marketplaceId in a saved config resolving to a stub; a proxy caching or mangling the response.
Related errors
- invalid_mcp_connection_payload
- invalid_plugin_payload
- invalid_billing_payload
- Failed to grant access (${response.status}).
- Failed to revoke access (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/6d87ee0c2a8fdcf8.
Report an issue: GitHub.