Mintplex-Labs/anything-llm · warning

Unprocessable Entity

Error message

Unprocessable Entity

What it means

Returned by POST /system/slash-command-presets/:slashCommandId when `SlashCommandPresets.update()` returns a falsy value (null/undefined). The handler first checks ownership via `SlashCommandPresets.get()` (which passes, returning ownsPreset), then calls update — if the update method returns null, line 1363 sends 422 Unprocessable Entity. This indicates the preset was found but the update operation could not produce a valid result, a semantic mismatch rather than a not-found (404) or server error (500).

Source

Thrown at server/endpoints/system.js:1363

        // Valid user running owns the preset if user session is valid.
        const ownsPreset = await SlashCommandPresets.get({
          userId: user?.id ?? null,
          id: Number(slashCommandId),
        });
        if (!ownsPreset)
          return response.status(404).json({ message: "Preset not found" });

        const updates = {
          command: formattedCommand,
          prompt: String(prompt),
          description: String(description),
        };

        const preset = await SlashCommandPresets.update(
          Number(slashCommandId),
          updates
        );
        if (!preset) return response.sendStatus(422);
        response.status(200).json({ preset: { ...ownsPreset, ...updates } });
      } catch (error) {
        console.error("Error updating slash command preset:", error);
        response.status(500).json({ message: "Internal server error" });
      }
    }
  );

  app.delete(
    "/system/slash-command-presets/:slashCommandId",
    [validatedRequest, flexUserRoleValid([ROLES.all])],
    async (request, response) => {
      try {
        const { slashCommandId } = request.params;
        const user = await userFromSession(request, response);

        // Valid user running owns the preset if user session is valid.
        const ownsPreset = await SlashCommandPresets.get({

View on GitHub (pinned to 526360e320)

Solutions

  1. Check if another request or process deleted the preset between the ownership check and the update call.
  2. Verify there are no unique constraints on the command column that would cause the update to silently fail.
  3. Retry the request — if it was a transient race condition, the retry should succeed.
  4. Inspect the SlashCommandPresets.update implementation to understand under what conditions it returns null (the model may swallow a DB error and return null instead).
Defensive patterns

Strategy: retry

Validate before calling

// Validate the preset exists and is owned before updating
async function verifyPresetOwnership(slashCommandId) {
  const res = await fetch(`/system/slash-command-presets/${slashCommandId}`, {
    method: 'POST', // this is the update endpoint; use GET for listing
  });
  return res.ok;
}

Try / catch

try {
  const res = await fetch(`/system/slash-command-presets/${id}`, {
    method: 'POST',
    body: JSON.stringify({ command, prompt, description }),
  });
  if (res.status === 422) {
    // Update returned null — preset may have been deleted concurrently
    // Retry once after re-fetching
    console.warn('Preset update returned 422, retrying...');
  } else if (res.status === 404) {
    throw new Error('Preset not found or not owned by user');
  }
} catch (e) {
  console.error('Preset update failed:', e.message);
}

Prevention

When it happens

Trigger: The preset exists at the ownership check (line 1346-1351) but the subsequent `SlashCommandPresets.update(Number(slashCommandId), updates)` returns null. This can happen in a race condition where the row is deleted between the get and update calls, or the update method internally validates and rejects the new values (e.g., duplicate command, constraint violation) returning null instead of throwing.

Common situations: Two concurrent requests update or delete the same preset. The update payload contains a command that passes the system-command collision check (line 1338) but violates a unique constraint at the database level. A model-layer validation in SlashCommandPresets.update silently returns null on constraint failure.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/32e3d2788153410e. Report an issue: GitHub.