paperclipai/paperclip · error

principalType must be 'agent' or 'user'

Error message

principalType must be 'agent' or 'user'

What it means

setGrants received a principalType outside the allowed set. Permission grants apply only to 'agent' or 'user' principals; the plugin passed some other value.

Source

Thrown at server/src/services/plugin-host-services.ts:3049

        const companyId = ensureCompanyId(params.companyId);
        await ensurePluginAvailableForCompany(companyId);
        const conditions = [
          eq(principalPermissionGrants.companyId, companyId),
          params.principalType ? eq(principalPermissionGrants.principalType, params.principalType) : undefined,
          params.principalId ? eq(principalPermissionGrants.principalId, params.principalId) : undefined,
        ].filter((condition): condition is NonNullable<typeof condition> => Boolean(condition));
        const rows = await db
          .select()
          .from(principalPermissionGrants)
          .where(and(...conditions))
          .orderBy(principalPermissionGrants.principalType, principalPermissionGrants.principalId, principalPermissionGrants.permissionKey);
        return rows.map(redactGrant);
      },
      async setGrants(params) {
        const companyId = ensureCompanyId(params.companyId);
        await ensurePluginAvailableForCompany(companyId);
        if (params.principalType !== "agent" && params.principalType !== "user") {
          throw new Error("principalType must be 'agent' or 'user'");
        }
        if (params.principalType === "agent") {
          requireInCompany("Agent", await agents.getById(params.principalId), companyId);
        } else {
          const membership = await access.getMembership(companyId, params.principalType as PrincipalType, params.principalId);
          if (!membership) throw new Error("Principal is not a member of this company");
        }
        await access.setPrincipalGrants(
          companyId,
          params.principalType as PrincipalType,
          params.principalId,
          params.grants.map((grant) => ({
            permissionKey: grant.permissionKey as PermissionKey,
            scope: grant.scope ? sanitizeRecord(grant.scope) : null,
          })),
          params.grantedByUserId ?? null,
        );
        await logPluginActivity({

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Set principalType to exactly 'agent' or 'user' in the request; any other value is rejected.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/services/plugin-host-services.ts:3040 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/f51cb8ea580adc0b. Report an issue: GitHub.