Skip to content

UUID primary keys not supported in relationship field validation #14948

@a4og5n

Description

@a4og5n

Payload CMS UUID Relationship Validation Issue

Summary

Payload CMS v3 does not properly handle UUID primary keys in relationship field validation. When creating a link with a UUID campaign ID, Payload's relationship validation converts the UUID string to a number (e.g., 5441d413-9eb8-4f22-adf6-29a0c8cc38df becomes 5441), causing validation to fail.

Environment

  • Payload CMS Version: 3.x
  • Database: PostgreSQL
  • Adapter: @payloadcms/db-postgres
  • Node Version: 25.2.1

Steps to Reproduce

  1. Configure a collection with UUID primary key:
export const Campaigns: CollectionConfig = {
  slug: 'campaigns',
  // ... other config
  hooks: {
    beforeChange: [
      async ({ data, operation }) => {
        if (operation === 'create' && !data.id) {
          data.id = generateUUID(); // Generate UUID
        }
        return data;
      },
    ],
  },
};
  1. Configure another collection with a relationship to the UUID collection:
export const Links: CollectionConfig = {
  slug: 'links',
  fields: [
    {
      name: 'campaign',
      type: 'relationship',
      relationTo: 'campaigns',
      required: true,
    },
  ],
};
  1. Create a campaign (works correctly):
const campaign = await payload.create({
  collection: 'campaigns',
  data: { name: 'Test Campaign', slug: 'test' },
});
// campaign.id = "5441d413-9eb8-4f22-adf6-29a0c8cc38df" ✅
  1. Try to create a link with the campaign UUID:
const link = await payload.create({
  collection: 'links',
  data: {
    destinationUrl: 'https://example.com',
    campaign: '5441d413-9eb8-4f22-adf6-29a0c8cc38df', // UUID string
  },
});

Expected Behavior

Link should be created successfully with the UUID campaign ID.

Actual Behavior

Validation error occurs:

Error: The following field is invalid: Campaign
Validation errors:
  - general: This relationship field has the following invalid relationships: 5441d413-9eb8-4f22-adf6-29a0c8cc38df 0

The error shows Payload is trying to query with params: 5441 instead of the full UUID, indicating it's converting the UUID to a number.

Database Schema

The database schema is correct:

CREATE TABLE campaigns (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  -- ... other fields
);

CREATE TABLE links (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  campaign_id UUID NOT NULL REFERENCES campaigns(id),
  -- ... other fields
);

Workarounds Attempted

  1. Custom validation function: Returns true to bypass validation, but Payload's built-in validation still runs
  2. beforeChange hook validation: Validates relationship manually, but Payload's validation runs first
  3. overrideAccess flag: Used in hooks, but doesn't affect relationship validation
  4. Direct database queries: Works, but bypasses Payload entirely

Impact

  • High: Blocks core functionality (creating links with UUID campaign relationships)
  • Affects: Any collection with UUID primary keys that are referenced by relationship fields
  • Workaround: Use direct database operations or revert to integer IDs

Related Issues

Additional Context

  • UUIDs are stored correctly in the database
  • READ operations work correctly with UUIDs
  • UPDATE operations work correctly with UUIDs
  • Only CREATE operations with relationship fields fail
  • The issue is specific to Payload's relationship validation, not database operations

Proposed Solution

Payload should:

  1. Detect when a relationship field references a collection with UUID primary keys
  2. Use string comparison instead of numeric conversion for UUID validation
  3. Support UUID primary keys in relationship validation queries

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions