{"record":{"id":"1c9a677c7f1e94b6","repo":"twentyhq/twenty","slug":"createfileupload-mutation-did-not-return-an-upload","errorCode":null,"errorMessage":"createFileUpload mutation did not return an upload target","messagePattern":"createFileUpload mutation did not return an upload target","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts","lineNumber":332,"sourceCode":"  fieldMetadataUniversalIdentifier: string;\n}): Promise<MediaUploadTarget> => {\n  const mutationResult = await metadataClient.mutation({\n    createFileUpload: {\n      __args: {\n        filename: fileName,\n        size: sizeBytes,\n        fileFolder: MEDIA_FILE_FOLDER,\n        fieldMetadataUniversalIdentifier,\n      },\n      fileId: true,\n      uploadUrl: true,\n      contentType: true,\n    },\n  });\n  const uploadTarget = mutationResult.createFileUpload;\n\n  if (isUndefined(uploadTarget)) {\n    throw new Error(\n      'createFileUpload mutation did not return an upload target',\n    );\n  }\n\n  return uploadTarget;\n};\n\nconst completeFileUpload = async ({\n  metadataClient,\n  fileId,\n}: {\n  metadataClient: InstanceType<typeof MetadataApiClient>;\n  fileId: string;\n}): Promise<string> => {\n  const mutationResult = await metadataClient.mutation({\n    completeFileUpload: {\n      __args: { fileId },\n      id: true,","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/import-call-recording-media.util.ts#L314-L350","documentation":"Before uploading media bytes, the flow calls the metadata `createFileUpload` mutation to obtain an upload target (`fileId`, `uploadUrl`, `contentType`). If the mutation result's `createFileUpload` field is `undefined`, the server did not return an upload target, so there is nowhere to PUT the bytes and the flow throws. The genql client returns `undefined` for a field the server omitted or for a union/error shape it did not select.","triggerScenarios":"The `fieldMetadataUniversalIdentifier` passed in does not match a file field on the object (so the server refuses to create an upload target), the authenticated user lacks permission to upload, the file size exceeds a server limit expressed as a null response, or the server returned an error payload that genql surfaces as an unset field.","commonSituations":"The audio/video field universal identifiers were renamed/removed; running against a workspace where the Call Recorder object/fields were not installed; permission/role misconfiguration on the installing user; a server-side upload quota reached.","solutions":["Verify `CALL_RECORDING_AUDIO_FIELD_UNIVERSAL_IDENTIFIER` / `CALL_RECORDING_VIDEO_FIELD_UNIVERSAL_IDENTIFIER` resolve to existing file-type fields on the call-recording object in this workspace.","Check the metadata client is authenticated with a role that can create file uploads on the call-recording object.","Log the full `mutationResult` (including any `errors` array from the genql response) to see the server-side reason the field was omitted.","Confirm `sizeBytes` is within the server's per-upload limit and that `fileFolder: 'FilesField'` is valid for this object."],"exampleFix":"// before\nconst uploadTarget = mutationResult.createFileUpload;\nif (isUndefined(uploadTarget)) {\n  throw new Error('createFileUpload mutation did not return an upload target');\n}\n\n// after — surface server errors and the requested identifier\nconst uploadTarget = mutationResult.createFileUpload;\nif (isUndefined(uploadTarget)) {\n  throw new Error(\n    `createFileUpload mutation did not return an upload target for ${fileName} (field=${fieldMetadataUniversalIdentifier}, size=${sizeBytes}); server errors: ${JSON.stringify(mutationResult.errors ?? [])}`,\n  );\n}","handlingStrategy":"validation","validationCode":"// Pre-flight: confirm the file field exists before requesting an upload target.\nconst fieldExists = await metadataClient.query({\n  fields: { __args: { filter: { universalIdentifier: { eq: fieldMetadataUniversalIdentifier } } }, edges: { node: { id: true } } },\n});\nif (!fieldExists.fields?.edges?.length) {\n  throw new Error(`File field ${fieldMetadataUniversalIdentifier} not found; cannot create upload target`);\n}","typeGuard":"const isUploadTarget = (v: unknown): v is { fileId: string; uploadUrl: string; contentType: string } =>\n  typeof v === 'object' &&\n  v !== null &&\n  typeof (v as any).fileId === 'string' &&\n  typeof (v as any).uploadUrl === 'string' &&\n  typeof (v as any).contentType === 'string';","tryCatchPattern":null,"preventionTips":["Verify the audio/video field universal identifiers resolve to file-type fields on the call-recording object in each workspace.","Always inspect `mutationResult.errors` when a genql field comes back undefined.","Confirm the acting role has create-file-upload permission on the object.","Ensure sizeBytes is within the server per-upload limit before calling createFileUpload."],"tags":["metadata-mutation","call-recorder","file-upload","graphql","configuration"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}