{"record":{"id":"80489bac25419109","repo":"pinojs/pino","slug":"only-one-of-target-or-targets-can-be-specified","errorCode":null,"errorMessage":"only one of target or targets can be specified","messagePattern":"only one of target or targets can be specified","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/transport.js","lineNumber":215,"sourceCode":"  }\n\n  let usesMultistream = false\n\n  // Backwards compatibility\n  const callers = typeof caller === 'string' ? [caller] : caller\n\n  // This will be eventually modified by bundlers\n  const bundlerOverrides = (typeof globalThis === 'object' &&\n    Object.prototype.hasOwnProperty.call(globalThis, '__bundlerPathsOverrides') &&\n    globalThis.__bundlerPathsOverrides &&\n    typeof globalThis.__bundlerPathsOverrides === 'object')\n    ? globalThis.__bundlerPathsOverrides\n    : Object.create(null)\n\n  let target = fullOptions.target\n\n  if (target && targets) {\n    throw new Error('only one of target or targets can be specified')\n  }\n\n  if (targets) {\n    target = bundlerOverrides['pino-worker'] || join(__dirname, 'worker.js')\n    options.targets = targets.filter(dest => dest.target).map((dest) => {\n      return {\n        ...dest,\n        target: fixTarget(dest.target)\n      }\n    })\n    options.pipelines = targets.filter(dest => dest.pipeline).map((dest) => {\n      return dest.pipeline.map((t) => {\n        return {\n          ...t,\n          level: dest.level, // duplicate the pipeline `level` property defined in the upper level\n          target: fixTarget(t.target)\n        }\n      })","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/pinojs/pino/blob/5aa62305c57709ebd6f6b7c328e8830eeb29b297/lib/transport.js#L197-L233","documentation":"The transport() function accepts either a single target or an array of targets, never both. lib/transport.js:215 throws when both options.target and options.targets are provided to avoid ambiguity about which stream configuration to build.","triggerScenarios":"pino({ transport: { target: 'pino-pretty', targets: [...] } }) — setting both keys on the same transport options object.","commonSituations":"Merging config objects where one sets target and another adds targets; programmatically building transport options with defaults that already include target.","solutions":["Remove either target or targets from the transport options","Wrap the single target as a one-element targets array: targets: [{ target: 'pino-pretty', options: {...} }]","Choose based on a condition: use targets when you need multiple destinations, otherwise target"],"exampleFix":"// before\npino({ transport: { target: 'pino/file', targets: [{ target: 'pino-pretty' }] } });\n// after\npino({ transport: { targets: [{ target: 'pino/file', options: { destination: './log' } }, { target: 'pino-pretty' }] } });","handlingStrategy":"type-guard","validationCode":"function normalizeTransport(t = {}) {\n  if (t.target && t.targets) {\n    throw new Error('transport options accept either target or targets, not both');\n  }\n  return t;\n}","typeGuard":"function isMultiTarget(t) { return Array.isArray(t && t.targets); }","tryCatchPattern":"try { logger = pino({ transport: t }); } catch (e) { if (/only one of target or targets/.test(e.message)) { logger = pino({ transport: { targets: [{ target: t.target }] } }); } else { throw e; } }","preventionTips":["Build transport config through a helper that merges target/targets exclusively","Prefer the targets array form when config is dynamic","Unit-test config merging so defaults never inject target alongside targets"],"tags":["logging","pino","transport","api-misuse"],"backgroundTag":"conflicting-options","analyzedSha":"5aa62305c57709ebd6f6b7c328e8830eeb29b297","analyzedAt":"2026-09-02T22:05:21.418Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}