{"record":{"id":"f2bd530ecbf8a331","repo":"windmill-labs/windmill","slug":"deletes3file-s3-key-is-required","errorCode":null,"errorMessage":"deleteS3File: s3 key is required","messagePattern":"deleteS3File: s3 key is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"typescript-client/client.ts","lineNumber":1048,"sourceCode":"}\n\n/**\n * Permanently delete a file from S3 by key.\n *\n * ```typescript\n * await wmill.deleteS3File({ s3: \"path/to/file.txt\" })\n * ```\n *\n * @param s3object - S3 object identifying the file to delete (must have `s3` set)\n * @param workspace - Workspace to delete from (defaults to the `WM_WORKSPACE` env var)\n */\nexport async function deleteS3File(\n  s3object: S3Object,\n  workspace: string | undefined = undefined\n): Promise<void> {\n  const s3Obj = parseS3Object(s3object);\n  if (!s3Obj.s3) {\n    throw new Error(\"deleteS3File: s3 key is required\");\n  }\n  await HelpersService.deleteS3File({\n    workspace: workspace ?? getWorkspace(),\n    fileKey: s3Obj.s3,\n    storage: s3Obj.storage,\n  });\n}\n\n/**\n * Sign S3 objects to be used by anonymous users in public apps\n * @param s3objects s3 objects to sign\n * @param expirySecs how long the signature stays valid, in seconds (default 43200 = 12h, clamped to [60, 604800])\n * @returns signed s3 objects\n */\nexport async function signS3Objects(\n  s3objects: S3Object[],\n  { expirySecs }: { expirySecs?: number } = {}\n): Promise<S3Object[]> {","sourceCodeStart":1030,"sourceCodeEnd":1066,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/typescript-client/client.ts#L1030-L1066","documentation":"Thrown by deleteS3File after parseS3Object when the resulting object has no `s3` key set. The S3Object payload type permits other storage identifiers, but this helper deletes strictly by raw S3 key, so a file-path-style or storage-scoped object is rejected before the API call.","triggerScenarios":"Calling deleteS3File with an S3Object whose parsed `s3` field is empty/undefined — e.g. an object built from a storage-only path.","commonSituations":"Passing a file path instead of an S3 key; an S3Object coming from an API response where only `storage` was populated; malformed \"storage/path\" string.","solutions":["Provide an S3Object with a valid s3 key","Use parseS3Object on a correct 'storage/key' string so s3 is populated","If the target is a storage (workspace) file rather than an S3 object, use the appropriate storage deletion API instead"],"exampleFix":"// before\nawait deleteS3File({ storage: 'my_folder' })\n// after\nawait deleteS3File({ s3: 'my_folder/file.txt', storage: 's3' })","handlingStrategy":"validation","validationCode":"const parsed = parseS3Object(s3object)\nif (!parsed.s3) throw new Error('S3Object must include an s3 key before deletion')","typeGuard":"function isDeletableS3Object(o: S3Object): boolean {\n  return !!parseS3Object(o).s3\n}","tryCatchPattern":"try {\n  await deleteS3File(s3object, workspace)\n} catch (e) {\n  if (e.message.includes('s3 key is required')) console.error('Provide an S3Object with an s3 key')\n  else throw e\n}","preventionTips":["Parse 'storage/key' strings with parseS3Object before constructing S3Objects","Distinguish S3 objects from workspace storage files — they use different APIs"],"tags":["s3","arguments","validation","file"],"backgroundTag":"missing-required-argument","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}