{"record":{"id":"b0679b3371492b66","repo":"vuejs/vue-cli","slug":"do-not-modify-webpack-output-publicpath-directly","errorCode":null,"errorMessage":"Do not modify webpack output.publicPath directly. Use the \"publicPath\" option in vue.config.js instead.","messagePattern":"Do not modify webpack output\\.publicPath directly\\. Use the \"publicPath\" option in vue\\.config\\.js instead\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@vue/cli-service/lib/Service.js","lineNumber":308,"sourceCode":"\n    // #2206 If config is merged by merge-webpack, it discards the __ruleNames\n    // information injected by webpack-chain. Restore the info so that\n    // vue inspect works properly.\n    if (config !== original) {\n      cloneRuleNames(\n        config.module && config.module.rules,\n        original.module && original.module.rules\n      )\n    }\n\n    // check if the user has manually mutated output.publicPath\n    const target = process.env.VUE_CLI_BUILD_TARGET\n    if (\n      !process.env.VUE_CLI_TEST &&\n      (target && target !== 'app') &&\n      config.output.publicPath !== this.projectOptions.publicPath\n    ) {\n      throw new Error(\n        `Do not modify webpack output.publicPath directly. ` +\n        `Use the \"publicPath\" option in vue.config.js instead.`\n      )\n    }\n\n    if (\n      !process.env.VUE_CLI_ENTRY_FILES &&\n      typeof config.entry !== 'function'\n    ) {\n      let entryFiles\n      if (typeof config.entry === 'string') {\n        entryFiles = [config.entry]\n      } else if (Array.isArray(config.entry)) {\n        entryFiles = config.entry\n      } else {\n        entryFiles = Object.values(config.entry || []).reduce((allEntries, curr) => {\n          return allEntries.concat(curr)\n        }, [])","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/vuejs/vue-cli/blob/7eb93c169c7520935252e2473387f923ef80d856/packages/@vue/cli-service/lib/Service.js#L290-L326","documentation":"During a non-app build (e.g. library mode, where VUE_CLI_BUILD_TARGET is set to something other than 'app'), Service.verifyConfig compares webpack's `config.output.publicPath` against the configured `publicPath` option. If they differ, a plugin/hook mutated publicPath directly, which breaks library path resolution, so it is rejected.","triggerScenarios":"In chainWebpack or configureWebpack, setting `config.output.publicPath = '...'` while building with a lib/wc target.","commonSituations":"Library builds with copy-pasted webpack snippets that override publicPath; plugins that assume app mode.","solutions":["Set `publicPath` in vue.config.js instead of mutating webpack output.","Remove the `config.output.publicPath = ...` line from your webpack hooks."],"exampleFix":"// vue.config.js — before (in chainWebpack)\nconfig.output.publicPath = '/assets/'\n// after\nmodule.exports = { publicPath: '/assets/' }","handlingStrategy":"validation","validationCode":"// inside your webpack hook — never mutate; assert equality instead\nconst expected = options.publicPath\nif (config.output.publicPath !== expected) {\n  throw new Error('Refusing to mutate output.publicPath; set the publicPath option instead')\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat output.publicPath as read-only in chainWebpack/configureWebpack.","Drive path/base-url options through vue.config.js fields."],"tags":["webpack","configuration","library-mode","public-path"],"backgroundTag":null,"analyzedSha":"7eb93c169c7520935252e2473387f923ef80d856","analyzedAt":"2026-08-13T10:13:37.803Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}