lfnovo/open-notebook · error · HTTPException

Failed to submit note embedding job

Error message

Failed to submit note embedding job

What it means

500 from POST /api/embed in the note path: note_item.save() returned a falsy command_id even though the note has non-empty content. Per the source comment, a missing command_id is tolerated when there is nothing to embed, but content-present + no command means the embedding job submission genuinely failed.

Source

Thrown at api/routers/embedding.py:102

                source_item = await Source.get(item_id)

                # Submit embed_source job (returns command_id for tracking)
                command_id = await source_item.vectorize()
                message = "Source embedding job submitted"

            elif item_type == "note":
                note_item = await Note.get(item_id)

                # Note.save() internally submits embed_note command and
                # returns command_id. Unlike Source.vectorize(), save()'s
                # embed submission is best-effort (a hiccup there shouldn't
                # fail an otherwise-successful note save) - but this
                # endpoint's whole point is submitting the embedding job,
                # so a submission failure here (content present, no
                # command_id) must still surface as a failure.
                command_id = await note_item.save()
                if not command_id and note_item.content and note_item.content.strip():
                    raise HTTPException(
                        status_code=500, detail="Failed to submit note embedding job"
                    )
                message = "Note embedding job submitted"

            return EmbedResponse(
                success=True,
                message=message,
                item_id=item_id,
                item_type=item_type,
                command_id=command_id,
            )

    except HTTPException:
        raise
    except NotFoundError:
        raise HTTPException(
            status_code=404, detail=f"{embed_request.item_type} not found"
        )

View on GitHub (pinned to a7de90d38a)

Solutions

  1. Check logs around the request for swallowed errors from note.save()/submit_command
  2. Verify the worker and DB tiers are running (make worker-start, make status)
  3. Re-save the note from the UI to re-trigger embedding once the stack is healthy
  4. If it persists, inspect the note record state (empty vs populated content) and the domain model's save() return contract
Defensive patterns

Strategy: retry

Validate before calling

const note = await api.getNote(noteId);
if (!note?.content?.trim()) throw new Error('Nothing to embed');

Try / catch

try {
  await api.embed({ item_id: noteId, item_type: 'note' });
} catch (e) {
  if (e.status === 500 && /note embedding job/i.test(e.detail)) {
    await delay(2000); await api.embed({ item_id: noteId, item_type: 'note' }); // one retry after worker check
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/embed with item_type='note' where the note has content but save() returns None/empty — the internal submit_command() call failed without raising (e.g. queue unavailable but errors are swallowed by the convenience method).

Common situations: Worker/queue infrastructure misconfigured so command submission no-ops, or an API version where the note domain model's save path silently skips embedding submission under certain states.

Related errors


AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27). Data as JSON: /api/errors/40e507f621681c3b. Report an issue: GitHub.