different-ai/openwork · error

member_not_found

member_not_found

Error message

member_not_found

What it means

resolveMemberIds validates each supplied member identifier with parseMemberId. If any value is not a well-formed member ID, it throws a 404 failure with code member_not_found before ever querying the database. This is a format-level rejection of a member reference in an LLM provider grant/credential payload.

Source

Thrown at ee/apps/den-api/src/routes/org/llm-providers.ts:300

function parseTeamId(value: string) {
  return normalizeDenTypeId("team", value)
}

async function resolveMemberIds(input: {
  organizationId: typeof LlmProviderTable.$inferSelect.organizationId
  values: string[]
}) {
  const uniqueValues = [...new Set(input.values)]
  if (uniqueValues.length === 0) {
    return [] as MemberId[]
  }

  const memberIds = uniqueValues.map((value) => {
    try {
      return parseMemberId(value)
    } catch {
      throw createFailure(404, "member_not_found")
    }
  })

  const rows = await db
    .select({ id: MemberTable.id })
    .from(MemberTable)
    .where(and(eq(MemberTable.organizationId, input.organizationId), inArray(MemberTable.id, memberIds), isNull(MemberTable.removedAt)))

  if (rows.length !== memberIds.length) {
    throw createFailure(404, "member_not_found")
  }

  return memberIds
}

async function resolveTeamIds(input: {
  organizationId: typeof LlmProviderTable.$inferSelect.organizationId
  values: string[]

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Inspect the request payload and replace the malformed value with a valid member table ID.
  2. Fetch valid member IDs via the org members list endpoint rather than constructing them client-side.
  3. Confirm you are sending member IDs (MemberTable.id), not user IDs.
  4. If the ID was stored previously, re-resolve it — members can be removed and re-added with new IDs.

Example fix

// before
{ "memberIds": ["alice@example.com"] }
// after
{ "memberIds": ["mem_9f2c1a7e-4b3d-4e2a-8f1b-2c9d5e6a7b8c"] }
Defensive patterns

Strategy: validation

Validate before calling

const MEMBER_ID_RE = /^(mem_|m_)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!values.every(v => MEMBER_ID_RE.test(v))) throw new Error('malformed member id');

Type guard

function isMemberId(v: unknown): v is string { return typeof v === 'string' && v.length > 0 && isUuidLike(v) }

Try / catch

try { await updateProviderGrants({ memberIds }) } catch (e) { if (e.code === 'member_not_found') await refreshMemberCache(); }

Prevention

When it happens

Trigger: An org LLM provider create/update request includes a member ID string that fails parseMemberId (malformed ID — wrong prefix, not a UUID, empty string).

Common situations: Client sends a user email, slug, or truncated ID instead of the canonical member ID; IDs copied from a different table (user id vs member id); stale hardcoded IDs after a migration.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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