Hi, I'm migrating a few Collections from PayloadCMS v2 to v3 and it's giving me an error with the following:
Type '"translations"' is not assignable to type 'CollectionSlug | CollectionSlug[]'.ts(2322)
(property) relationTo: CollectionSlug[]Prior to version 3, the property 'relationTo' could be assigned to a String corresponding to the Slug of the collection. Not sure what changed.
Here's the code snippet:
const personFields: Field[] = [
{ name: 'matchName' , type: 'relationship', relationTo: 'translations', hasMany: true },
{ name: 'shortName' , type: 'relationship', relationTo: 'translations', hasMany: true },
{ name: 'firstName' , type: 'text' },
{ name: 'lastName' , type: 'text' },
{ name: 'image' , type: 'text' },
{ name: 'video' , type: 'text' },
{ name: 'vbn_folder', type: 'text' },
{ name: 'team' , type: 'relationship', relationTo: 'teams', admin: { readOnly: true } },
]Could you share the import for the Field type?
This is the whole file.
import { CollectionConfig, CollectionAfterChangeHook, Field, CollectionAfterLoginHook } from 'payload'
import { cache } from '../middlewares';
// Languages Collection
const languageFields: Field[] = [
{ name: 'name', type: 'text' },
{ name: 'isDefault', type: 'checkbox' }
]
const Languages: CollectionConfig = {
slug: 'languages',
admin: { useAsTitle: 'name' },
fields: languageFields,
access: {
read : () => true, // allows public GET
update: () => true, // allows public PATCH
create: () => true, // allows public POST
delete: () => true, // allows public DELETE
},
}
const translationFields: Field[] = [
{ name: 'key' , type: 'text' },
{ name: 'language', type: 'relationship', relationTo: 'languages' },
{ name: 'value' , type: 'text' },
]
const afterChangeHook: CollectionAfterChangeHook = async ({ doc }) => { cache.deletekeys(['&target=']); };
const Translations: CollectionConfig = {
slug: 'translations',
admin: { useAsTitle: 'name' },
fields: translationFields,
access: {
read : () => true, // allows public GET
update: () => true, // allows public PATCH
create: () => true, // allows public POST
delete: () => true, // allows public DELETE
}
};
export { Languages, Translations };I think i've tracked down the problem to the generated types
But made me go against another problem
Zod is screaming out of its lungs that the validation is not working
For context, Zod is being called only here:
import { z } from 'zod';
import dotenv from "dotenv";
dotenv.config();
const isBoolean = (bool: string) => bool == String(true) || bool == String(false);
const isNumber = (num: string) => !Number.isNaN(Number(num));
const envSchema = z.object({
PAYLOAD_PUBLIC_DATABASE_URI: z.string()
.refine((URI: string) => URI.startsWith("mongodb://"), "Invalid Database URI")
,
PAYLOAD_PUBLIC_PAYLOAD_SECRET: z.string(),
PAYLOAD_PUBLIC_OPTA_KEY: z.string(),
PAYLOAD_PUBLIC_CACHE_ONEDAY_MS: z.string()
.refine(isNumber, "Cache time is not a Number")
.refine((num: string) => Number(num) >= 0, "Cache time cannot be negative.")
,
PAYLOAD_PUBLIC_CACHE_FIVEMINUTES_MS: z.string()
.refine(isNumber, "Cache time is not a Number")
.refine((num: string) => Number(num) >= 0, "Cache time cannot be negative.")
,
PAYLOAD_PUBLIC_TZ: z.string().refine(
(tz: string) => Intl.supportedValuesOf('timeZone').includes(tz),
"Timezone can't be recognized."
),
PAYLOAD_PUBLIC_DISABLE_LOGGING: z.string().refine(isBoolean, "Not a boolean."),
PAYLOAD_PUBLIC_SHEETS_TRANSLATE_ENABLE: z.string().refine(isBoolean, "Not a boolean."),
PAYLOAD_PUBLIC_FLAGS_PATH: z.string(),
PAYLOAD_PUBLIC_TEAM_LOGO_PATH: z.string(),
PAYLOAD_PUBLIC_TEAM_BIG_LOGO_PATH: z.string(),
PAYLOAD_PUBLIC_TEAM_SMALL_LOGO_PATH: z.string(),
PAYLOAD_PUBLIC_COMPETITIONS_LOGO: z.string(),
PAYLOAD_PUBLIC_COMPETITIONS_SMALL_LOGO: z.string(),
PAYLOAD_PUBLIC_PLAYER_PHOTO_PATH: z.string(),
PAYLOAD_PUBLIC_PLAYER_BIG_PHOTO_PATH: z.string(),
PAYLOAD_PUBLIC_PLAYER_SMALL_PHOTO_PATH: z.string(),
PAYLOAD_PUBLIC_SHEET_ID: z.string(),
PAYLOAD_PUBLIC_SHEET_CREDENTIALS_FILE: z.string(),
PAYLOAD_PUBLIC_SEASONS_ID: z.string(),
PAYLOAD_PUBLIC_LANGUAGES: z.string(),
NEXT_PUBLIC_SERVER_URL: z.string(),
});
type Env = z.infer<typeof envSchema>;
declare global {
namespace NodeJS {
interface ProcessEnv extends Env { }
}
}
console.log(`Process Env:
${process.env}`)
export const ENV: Env = envSchema.parse(process.env);What errors is zod showing
That every single one of the properties are getting undefined (Invalid Types):
ZodError: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"PAYLOAD_PUBLIC_DATABASE_URI"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"PAYLOAD_PUBLIC_PAYLOAD_SECRET"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"PAYLOAD_PUBLIC_OPTA_KEY"
],
"message": "Required"
}
]
at get error [as error] (file:///D:/backoffice-keystone-opta/backoffice-opta/node_modules/.pnpm/zod@3.23.8/node_modules/zod/lib/index.mjs?tsx-namespace=1732276123176:587:31)
at ZodObject.parse (file:///D:/backoffice-keystone-opta/backoffice-opta/node_modules/.pnpm/zod@3.23.8/node_modules/zod/lib/index.mjs?tsx-namespace=1732276123176:692:22)
at <anonymous> (D:\backoffice-keystone-opta\backoffice-opta\src\env.ts:57:35)
at ModuleJob.run (node:internal/modules/esm/module_job:234:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:473:24)
at async bin (D:\backoffice-keystone-opta\backoffice-opta\node_modules\.pnpm\payload@3.0.2_graphql@16.9.0_monaco-editor@0.52.0_react-dom@19.0.0-rc-65a56d0e-20241020_react_fp54bueddpkts7o7cdap7tptuu\node_modules\payload\dist\bin\index.js:47:27)
at async start (file:///D:/backoffice-keystone-opta/backoffice-opta/node_modules/.pnpm/payload@3.0.2_graphql@16.9.0_monaco-editor@0.52.0_react-dom@19.0.0-rc-65a56d0e-20241020_react_fp54bueddpkts7o7cdap7tptuu/node_modules/payload/bin.js:30:7) {
issues: [
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_DATABASE_URI' ],
message: 'Required'
},
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_PAYLOAD_SECRET' ],
message: 'Required'
},
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_OPTA_KEY' ],
message: 'Required'
}
],
addIssue: [Function (anonymous)],
addIssues: [Function (anonymous)],
errors: [
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_DATABASE_URI' ],
message: 'Required'
},
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_PAYLOAD_SECRET' ],
message: 'Required'
},
{
code: 'invalid_type',
expected: 'string',
received: 'undefined',
path: [ 'PAYLOAD_PUBLIC_OPTA_KEY' ],
message: 'Required'
}
]
}Oh wait a min
Gimme a sec
I think you need to be using NEXT_PUBLIC
Wait. its no longer PAYLOAD_PUBLIC_?
I dont believe so
Ok, so zod having a tantrum had its reasoning
I was missing those in the .env file
Here's a snippet of the migration docs
Keep in mind this is only for client values, some of those you shared shouldnt be client values.
F, so the v3 docs need to be updated. Cuz it still says that PAYLOAD_PUBLIC_ is the way to go
I'm aware, its just for development purposes only.
Would you mind sharing where in the docs it still says PAYLOAD_PUBLIC? I can look to resolve it.
Oh wait a min
Since 2 days ago it changed
Ok, I found what the problem was. I had to declare the Collections in the PayloadConfig and generate the Types. I ended up solving the conflicts and now it does recognize 'translations' as a CollectionSlug
Star
Discord
online
Get dedicated engineering support directly from the Payload team.