{"record":{"id":"e08f88d8959e40ef","repo":"angular/angular-cli","slug":"path-option-is-required","errorCode":null,"errorMessage":"path option is required","messagePattern":"path option is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/core/src/workspace/json/writer.ts","lineNumber":42,"sourceCode":"  path?: string,\n  options: {\n    schema?: string;\n  } = {},\n): Promise<void> {\n  const metadata = (workspace as JsonWorkspaceDefinition)[JsonWorkspaceSymbol];\n\n  if (metadata) {\n    if (!metadata.hasChanges) {\n      return;\n    }\n    // update existing JSON workspace\n    const data = updateJsonWorkspace(metadata);\n\n    return host.writeFile(path ?? metadata.filePath, data);\n  } else {\n    // serialize directly\n    if (!path) {\n      throw new Error('path option is required');\n    }\n\n    const obj = convertJsonWorkspace(workspace, options.schema);\n    const data = JSON.stringify(obj, null, 2);\n\n    return host.writeFile(path, data);\n  }\n}\n\nfunction convertJsonWorkspace(workspace: WorkspaceDefinition, schema?: string): JsonObject {\n  const obj = {\n    $schema: schema || './node_modules/@angular/cli/lib/config/schema.json',\n    version: 1,\n    ...workspace.extensions,\n    ...(isEmpty(workspace.projects)\n      ? {}\n      : { projects: convertJsonProjectCollection(workspace.projects) }),\n  };","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/core/src/workspace/json/writer.ts#L24-L60","documentation":"writeJsonWorkspace can serialize a workspace in two modes. In update mode it can infer the output path from the metadata; in direct-serialize mode (when no updater produced metadata), it has no way to know where to write, so a `path` option is mandatory. Passing no path in the non-update path throws this error.","triggerScenarios":"Calling writeJsonWorkspace(workspace, host, { /* no `path` */ }) without an updater function that produces metadata with a filePath — i.e. serializing the workspace directly via convertJsonWorkspace without specifying where to write.","commonSituations":"Script that reads a workspace, modifies it via convertJsonWorkspace, and calls the writer forgetting the path option; refactors that removed the updater (and thus the metadata filePath) but left the options object unchanged.","solutions":["Pass the target file path in the options: writeJsonWorkspace(workspace, host, { path: 'angular.json' })","Or provide an updater function so updateJsonWorkspace mode is used and the original metadata.filePath is used","If wrapping this API, default the path from workspace.definition.filePath before calling"],"exampleFix":"// before\nawait writeJsonWorkspace(workspace, host, {});\n// after\nawait writeJsonWorkspace(workspace, host, { path: 'angular.json' });","handlingStrategy":"validation","validationCode":"function assertWriteOptions(opts) {\n  if (!opts || !(typeof opts.path === 'string' || typeof opts.updater === 'function')) {\n    throw new Error('writeJsonWorkspace requires `path` or an updater.');\n  }\n}","typeGuard":"function hasPath(o) {\n  return typeof o === 'object' && o !== null && typeof o.path === 'string' && o.path.length > 0;\n}","tryCatchPattern":"try {\n  await writeJsonWorkspace(workspace, host, opts);\n} catch (err) {\n  if (err.message === 'path option is required') {\n    await writeJsonWorkspace(workspace, host, { ...opts, path: 'angular.json' });\n  } else throw err;\n}","preventionTips":["Always pass { path: 'angular.json' } when writing without an updater","Wrap the writer in a helper that defaults the path from workspace metadata","Keep the path consistent with the file used in parseWorkspace"],"tags":["workspace","options-validation","angular-cli"],"backgroundTag":"missing-required-option","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}