{"record":{"id":"062c17d925718980","repo":"microsoft/playwright","slug":"cannot-close-a-directory","errorCode":null,"errorMessage":"Cannot close a directory","messagePattern":"Cannot close a directory","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/dispatchers/writableStreamDispatcher.ts","lineNumber":60,"sourceCode":"  }\n\n  async write(params: channels.WritableStreamWriteParams, progress: Progress): Promise<channels.WritableStreamWriteResult> {\n    if (typeof this._object.streamOrDirectory === 'string')\n      throw new Error('Cannot write to a directory');\n    const stream = this._object.streamOrDirectory;\n    await progress.race(new Promise<void>((fulfill, reject) => {\n      stream.write(params.binary, error => {\n        if (error)\n          reject(error);\n        else\n          fulfill();\n      });\n    }));\n  }\n\n  async close(params: channels.WritableStreamCloseParams, progress: Progress): Promise<void> {\n    if (typeof this._object.streamOrDirectory === 'string')\n      throw new Error('Cannot close a directory');\n    const stream = this._object.streamOrDirectory;\n    await progress.race(new Promise<void>(fulfill => stream.end(fulfill)));\n    if (this._object.lastModifiedMs)\n      await progress.race(fs.promises.utimes(this.path(), new Date(this._object.lastModifiedMs), new Date(this._object.lastModifiedMs)));\n  }\n\n  path(): string {\n    if (typeof this._object.streamOrDirectory === 'string')\n      return this._object.streamOrDirectory;\n    return this._object.streamOrDirectory.path as string;\n  }\n\n  override _onDispose() {\n    if (typeof this._object.streamOrDirectory !== 'string')\n      this._object.streamOrDirectory.destroy();\n  }\n}\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/dispatchers/writableStreamDispatcher.ts#L42-L78","documentation":"Symmetric with the write guard: WritableStreamDispatcher.close() throws when streamOrDirectory is a directory string, because there is no underlying fs.WriteStream to end(). The close path exists to flush a real stream; a directory marker has nothing to flush.","triggerScenarios":"Calling close() on a WritableStreamDispatcher that was constructed with a directory path rather than a write stream; the directory branch is used internally and closing it is invalid.","commonSituations":"See trigger scenarios.","solutions":["Ensure the writable stream wraps an actual file (fs.WriteStream), not a directory string.","Use a full file path for save targets so a real stream is created.","Avoid calling close on directory-marker dispatchers."],"exampleFix":"// before — directory path produces a directory marker\nconst stream = new WritableStreamDispatcher(scope, '/tmp/out/');\nawait stream.close(); // throws\n// after\nconst stream = new WritableStreamDispatcher(scope, fs.createWriteStream('/tmp/out/file.bin'));\nawait stream.close();","handlingStrategy":"validation","validationCode":"// Only close a stream that wraps an actual fs.WriteStream.\nif (typeof streamOrDirectory !== 'string') {\n  await stream.close();\n}","typeGuard":"// Distinguish a writable stream from a directory marker.\nfunction isWriteStream(s: fs.WriteStream | string): s is fs.WriteStream {\n  return typeof s !== 'string';\n}","tryCatchPattern":null,"preventionTips":["Do not construct directory-marker dispatchers when you intend to write a file.","Pass fs.createWriteStream(file) so close() has a real stream to end.","Keep save targets as concrete file paths."],"tags":["filesystem","save-as","protocol"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}