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

  1. Inspect the actual PUT response body and compare against parseSkillResponse's expectations.
  2. Update the parser or the API so the save response includes all required fields.
  3. Verify persistence with a refetch of useSkill; if the data is correct, the failure is response-shape only.
  4. 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

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


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