vxcontrol/pentagi · error

knowledge: get user document %s: %w

Error message

knowledge: get user document %s: %w

What it means

GetUserDocument fetches a knowledge document by UUID enforcing ownership via user_id in cmetadata. Failure of the SQLC query GetUserKnowledgeDocument (not found, not owned, DB down) is wrapped as 'knowledge: get user document <id>'.

Source

Thrown at backend/pkg/database/knowledge/knowledge.go:327

// ---- GetDocument (admin) ----------------------------------------------------

func (ks *knowledgeStore) GetDocument(ctx context.Context, id string) (*model.KnowledgeDocument, error) {
	row, err := ks.db.GetKnowledgeDocument(ctx, id)
	if err != nil {
		return nil, fmt.Errorf("knowledge: get document %s: %w", id, err)
	}
	return rowToModel(row.ID, row.Document, nullStr(row.Cmetadata), true), nil
}

// ---- GetUserDocument (user-scoped) ------------------------------------------

func (ks *knowledgeStore) GetUserDocument(ctx context.Context, userID int64, id string) (*model.KnowledgeDocument, error) {
	row, err := ks.db.GetUserKnowledgeDocument(ctx, database.GetUserKnowledgeDocumentParams{
		Uuid:   id,
		UserID: nsOf(strconv.FormatInt(userID, 10)),
	})
	if err != nil {
		return nil, fmt.Errorf("knowledge: get user document %s: %w", id, err)
	}
	return rowToModel(row.ID, row.Document, nullStr(row.Cmetadata), true), nil
}

// ---- SearchDocuments (admin) ------------------------------------------------

func (ks *knowledgeStore) SearchDocuments(ctx context.Context, query string, filter *model.KnowledgeFilter, limit int) ([]*model.KnowledgeDocumentWithScore, error) {
	return ks.doSearch(ctx, 0, query, filter, limit)
}

// ---- SearchUserDocuments (user-scoped) --------------------------------------

func (ks *knowledgeStore) SearchUserDocuments(ctx context.Context, userID int64, query string, filter *model.KnowledgeFilter, limit int) ([]*model.KnowledgeDocumentWithScore, error) {
	return ks.doSearch(ctx, userID, query, filter, limit)
}

// doSearch performs a parameterised vector similarity search and returns
// matched documents with their cosine-similarity scores and correct UUIDs.

View on GitHub (pinned to ea665308ba)

Solutions

  1. Verify the document exists and is owned by the given userID (check cmetadata user_id in the database).
  2. Map sql.ErrNoRows to a 404-style not-found response for the UI instead of leaking a DB error.
  3. Ensure the userID namespace string (nsOf) format matches what was written at CreateDocument time.
  4. Check DB connectivity if the wrapped error indicates connection failure.

Example fix

// before
if err != nil {
    return nil, fmt.Errorf("knowledge: get user document %s: %w", id, err)
}
// after
if errors.Is(err, sql.ErrNoRows) {
    return nil, fmt.Errorf("knowledge: document %s not found for user", id) // 404 upstream
}
if err != nil {
    return nil, fmt.Errorf("knowledge: get user document %s: %w", id, err)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if _, err := uuid.Parse(id); err != nil || userID <= 0 {
    return nil, fmt.Errorf("invalid id or user")
}

Type guard

func isNotFoundOrForbidden(err error) bool {
    return errors.Is(err, sql.ErrNoRows) // ownership miss and absence both surface as no rows
}

Try / catch

doc, err := store.GetUserDocument(ctx, userID, id)
if err != nil {
    if isNotFoundOrForbidden(err) {
        return ErrNotFound // never reveal existence of other users' docs
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetUserDocument or the user-scoped Update/Rename/Delete wrappers with a document id that either does not exist or belongs to a different user (UUID + UserID pair has no row).

Common situations: A user tries to access another user's document id (authorization failure); user_id stored under a different namespace format than nsOf produces; stale id from a deleted document.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/4bcb15a8c0482272. Report an issue: GitHub.