{"record":{"id":"cf8c7e57400be569","repo":"twentyhq/twenty","slug":"getpublicasseturl-can-only-be-called-from-within-a","errorCode":null,"errorMessage":"getPublicAssetUrl can only be called from within a logic function or front component","messagePattern":"getPublicAssetUrl can only be called from within a logic function or front component","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-sdk/src/sdk/utils/get-public-asset-url.ts","lineNumber":25,"sourceCode":"  token: string,\n): { workspaceId: string; applicationId: string } => {\n  const payload = JSON.parse(atob(token.split('.')[1]));\n\n  return {\n    workspaceId: payload.workspaceId,\n    applicationId: payload.applicationId,\n  };\n};\n\n// Returns the public URL for a file in the app's public/ directory.\n// Works in both logic functions and front components.\n// The path is relative to the public/ folder (e.g. \"images/logo.png\").\nexport const getPublicAssetUrl = (path: string): string => {\n  const apiUrl = process.env[DEFAULT_API_URL_NAME];\n  const token = process.env[DEFAULT_APP_ACCESS_TOKEN_NAME];\n\n  if (!apiUrl || !token) {\n    throw new Error(\n      'getPublicAssetUrl can only be called from within a logic function or front component',\n    );\n  }\n\n  const { workspaceId, applicationId } = decodeTokenPayload(token);\n  const withoutLeadingSlash = path.startsWith('/') ? path.slice(1) : path;\n  const withPublicPrefix = withoutLeadingSlash.startsWith('public/')\n    ? withoutLeadingSlash\n    : `public/${withoutLeadingSlash}`;\n\n  const encodedPath = withPublicPrefix\n    .split('/')\n    .map(encodeURIComponent)\n    .join('/');\n\n  return `${apiUrl}/public-assets/${workspaceId}/${applicationId}/${encodedPath}`;\n};\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-sdk/src/sdk/utils/get-public-asset-url.ts#L7-L43","documentation":"Thrown by getPublicAssetUrl when process.env[DEFAULT_API_URL_NAME] or process.env[DEFAULT_APP_ACCESS_TOKEN_NAME] is unset. Twenty injects these two env vars only while dispatching a logic function or front component, so the guard detects calls from any other execution context and refuses to build a URL it cannot authenticate or scope.","triggerScenarios":"Calling getPublicAssetUrl('images/logo.png') outside a Twenty-dispatched logic/front runtime: in a Jest test, a Node CLI script, a module top-level statement, or a worker that never received the app access token.","commonSituations":"Unit-testing SDK helpers without seeding the two env vars; importing SDK code into server bootstrap that runs before the runtime sets the token; SSR/build-time evaluation of a module that transitively reaches getPublicAssetUrl.","solutions":["Move the call inside a logic function or front component handler body so Twenty's runtime has already set the env vars.","In tests, set process.env[DEFAULT_API_URL_NAME] and process.env[DEFAULT_APP_ACCESS_TOKEN_NAME] (import the constant names from twenty-shared/application) before invoking.","Avoid invoking getPublicAssetUrl at module load time; defer it into the handler so it only runs in runtime context."],"exampleFix":"// before (module scope, breaks)\nexport const logo = getPublicAssetUrl('images/logo.png');\n\n// after (inside a logic/front handler)\nexport const handler = () => {\n  const logo = getPublicAssetUrl('images/logo.png');\n  return { logo };\n};","handlingStrategy":"validation","validationCode":"import { DEFAULT_API_URL_NAME, DEFAULT_APP_ACCESS_TOKEN_NAME } from 'twenty-shared/application';\n\nconst canCallGetPublicAssetUrl = (): boolean =>\n  Boolean(process.env[DEFAULT_API_URL_NAME]) &&\n  Boolean(process.env[DEFAULT_APP_ACCESS_TOKEN_NAME]);\n\n// before calling:\nif (!canCallGetPublicAssetUrl()) {\n  // skip or seed env vars in tests\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only import and call getPublicAssetUrl from within logic function or front component handlers.","In unit tests, set both DEFAULT_API_URL_NAME and DEFAULT_APP_ACCESS_TOKEN_NAME env vars before invoking.","Never evaluate getPublicAssetUrl at module top level; defer into the handler body."],"tags":["sdk","environment","runtime-context","configuration"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}