different-ai/openwork · error
Skill update response was incomplete.
Error message
Skill update response was incomplete.
What it means
useUpdateSkill PUTs skill changes and, on a 2xx response, parses the body with parseSkillResponse. When the returned skill object doesn't match the expected shape (parser returns null), it throws 'Skill update response was incomplete.' The update itself likely persisted; only the response validation failed.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/skill-data.tsx:166
return useMutation({
mutationFn: async (input: { skillId: string; draft: SkillDraft }): Promise<DenSkill> => {
const { response, payload } = await requestJson(
`/v1/config-objects/${encodeURIComponent(input.skillId)}/versions`,
{
method: "POST",
body: JSON.stringify({
input: { rawSourceText: skillSourceFromDraft(input.draft) },
reason: "Updated from Den Web",
}),
},
15000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Failed to save skill (${response.status}).`);
}
const skill = parseSkillResponse(payload);
if (!skill) {
throw new Error("Skill update response was incomplete.");
}
return skill;
},
onSuccess: async () => {
await Promise.all([
queryClient.invalidateQueries({ queryKey: skillQueryKeys.all }),
queryClient.invalidateQueries({ queryKey: pluginQueryKeys.detail(pluginId) }),
]);
},
});
}
export function useDeleteSkill(pluginId: string) {
const queryClient = useQueryClient();
const { runReauthableAction } = useOrgDashboard();
return useMutation({
mutationFn: async (skillId: string): Promise<string> => {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Inspect the actual PUT response body and compare against parseSkillResponse's expectations.
- Update the parser or the API so the save response includes all required fields.
- Verify persistence with a refetch of useSkill; if the data is correct, the failure is response-shape only.
- Clear stale react-query cache after fixing so the UI refetches a well-formed detail.
Example fix
// before
const skill = parseSkillResponse(payload);
if (!skill) throw new Error("Skill update response was incomplete.");
// after
const skill = parseSkillResponse(payload) ?? parseSkillResponse((payload as {data?: unknown})?.data);
if (!skill) throw new Error("Skill update response was incomplete."); Defensive patterns
Strategy: validation
Validate before calling
function looksLikeUpdatedSkill(v: unknown): boolean {
return isRecord(v) && typeof v.id === "string" && typeof v.name === "string";
} Type guard
function isSkill(v: unknown): v is Skill {
return isRecord(v) && typeof v.id === "string" && typeof v.name === "string";
} Try / catch
try {
await updateSkill(input);
} catch (e) {
if (e instanceof Error && e.message === "Skill update response was incomplete.") {
// update likely persisted; refetch detail to confirm instead of re-saving blindly
await queryClient.invalidateQueries({ queryKey: skillQueryKeys.all });
} else throw e;
} Prevention
- Confirm persistence via refetch instead of retrying the PUT
- Assert response shape in API contract tests
- Handle empty 200 bodies from proxies explicitly
When it happens
Trigger: PUT skill detail returns ok but body is missing required skill fields or is not a record, so parseSkillResponse returns null.
Common situations: Server/client schema mismatch after a deploy; endpoint returns an empty body on save; API returns an alternate shape (e.g. wrapped in {data: ...}) the parser doesn't recognize.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Skill create response was incomplete.
- invalid_cloud_plugin
- Skill detail response was incomplete.
- The Workflow response was invalid.
- The snapshot response was invalid.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/217b4d509db56cf2.
Report an issue: GitHub.