{"record":{"id":"2a6281f888c614f9","repo":"microsoft/playwright","slug":"path-is-not-available-when-connecting-remotely-us","errorCode":null,"errorMessage":"Path is not available when connecting remotely. Use saveAs() to save a local copy.","messagePattern":"Path is not available when connecting remotely\\. Use saveAs\\(\\) to save a local copy\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/client/artifact.ts","lineNumber":34,"sourceCode":"\nimport fs from 'fs';\n\nimport { ChannelOwner } from './channelOwner';\nimport { Stream } from './stream';\nimport { mkdirIfNeeded } from './fileUtils';\nimport { kNoTimeout } from './timeoutSettings';\n\nimport type * as channels from './channels';\nimport type { Readable } from 'stream';\n\nexport class Artifact extends ChannelOwner<channels.ArtifactChannel> {\n  static from(channel: channels.ArtifactChannel): Artifact {\n    return (channel as any)._object;\n  }\n\n  async pathAfterFinished(): Promise<string> {\n    if (this._connection.isRemote())\n      throw new Error(`Path is not available when connecting remotely. Use saveAs() to save a local copy.`);\n    return (await this._channel.pathAfterFinished({}, kNoTimeout)).value;\n  }\n\n  async saveAs(path: string): Promise<void> {\n    if (!this._connection.isRemote()) {\n      await this._channel.saveAs({ path }, kNoTimeout);\n      return;\n    }\n\n    const result = await this._channel.saveAsStream({}, kNoTimeout);\n    const stream = Stream.from(result.stream);\n    await mkdirIfNeeded(path);\n    await new Promise((resolve, reject) => {\n      stream.stream().pipe(fs.createWriteStream(path))\n          .on('finish' as any, resolve)\n          .on('error' as any, reject);\n    });\n  }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/client/artifact.ts#L16-L52","documentation":"Thrown by Artifact.pathAfterFinished() when the connection is remote (a thin/remote client over WS). Remote clients cannot access the server's filesystem path, so only saveAs(path) (which streams the artifact) is allowed. The guard is `this._connection.isRemote()`.","triggerScenarios":"Calling `download.path()` or `artifact.pathAfterFinished()` after connecting via BrowserType.connect() to a remote server, or using playwright-client in thin-client mode. Applies to downloads, video artifacts, and traces created server-side.","commonSituations":"Reusing code that calls download.path() locally in a CI step that now connects to a remote browser service; running tests against Browserless/cloud providers where the browser runs on another host.","solutions":["Use saveAs() to stream a local copy: `await download.saveAs('/tmp/file')`.","Restructure code to always use saveAs() so it works both local and remote.","If you need the path pattern, build it locally after saveAs rather than relying on the server path."],"exampleFix":"// before\nconst p = await download.path();\n// after\nconst p = '/tmp/downloaded.bin';\nawait download.saveAs(p);","handlingStrategy":"type-guard","validationCode":"const isRemote = (artifact as any)._connection?.isRemote?.();\nif (isRemote) {\n  await artifact.saveAs(localPath); // never call path()\n} else {\n  const p = await artifact.pathAfterFinished();\n}","typeGuard":"function isRemoteArtifact(a: any): boolean {\n  return !!a?._connection?.isRemote?.();\n}","tryCatchPattern":null,"preventionTips":["Default to saveAs() everywhere; it works in both local and remote modes.","Avoid download.path() in code that may run against a remote browser service."],"tags":["artifact","remote","downloads","filesystem"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}