{"record":{"id":"df08c996bceb83b9","repo":"mastra-ai/mastra","slug":"experiment-invalid-target","errorCode":"EXPERIMENT_INVALID_TARGET","errorMessage":"targetType and targetId must be provided together (got targetType: ${args?.targetType ?? 'none'}, targetId: ${args?.targetId ?? 'none'})","messagePattern":"targetType and targetId must be provided together \\(got targetType: (.+?), targetId: (.+?)\\)","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/datasets/dataset.ts","lineNumber":656,"sourceCode":"    provenance?: ExperimentProvenance;\n    grouping?: { experimentSetId?: string; comparisonId?: string; variantId?: string; trialIndex?: number };\n    /** Dataset version to pin. Defaults to the dataset's current version. */\n    version?: number;\n  }): Promise<{\n    experimentId: string;\n    status: ExperimentStatus;\n    totalItems: number;\n    datasetVersion: number;\n    /** The persisted start timestamp — stable across retried creates with the same `id`. */\n    startedAt: Date | null;\n  }> {\n    const experimentsStore = await this.#getExperimentsStore();\n    const datasetsStore = await this.#getDatasetsStore();\n\n    const hasTargetType = args?.targetType !== undefined;\n    const hasTargetId = args?.targetId !== undefined;\n    if (hasTargetType !== hasTargetId) {\n      throw new MastraError({\n        id: 'EXPERIMENT_INVALID_TARGET',\n        text: `targetType and targetId must be provided together (got targetType: ${args?.targetType ?? 'none'}, targetId: ${args?.targetId ?? 'none'})`,\n        domain: 'STORAGE',\n        category: 'USER',\n      });\n    }\n    if (args?.scorers?.length && !hasTargetType) {\n      throw new MastraError({\n        id: 'EXPERIMENT_INVALID_TARGET',\n        text: 'scorers require a target: without a target Mastra never executes or scores items; submit flat scores via submitExperimentResult instead',\n        domain: 'STORAGE',\n        category: 'USER',\n      });\n    }\n    // Validate the target exists in this Mastra registry at create time so a\n    // typo fails fast instead of failing on the first runExperimentItem call.\n    if (hasTargetType) {\n      const resolved = await resolveTarget(this.#mastra, args!.targetType!, args!.targetId!);","sourceCodeStart":638,"sourceCodeEnd":674,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/datasets/dataset.ts#L638-L674","documentation":"createExperiment requires targetType and targetId to be supplied together. Providing exactly one is ambiguous (a target type with no id or vice versa), so Mastra rejects it at creation time.","triggerScenarios":"Calling createExperiment with only targetType, or only targetId, set in args.","commonSituations":"Building args conditionally where one field is set but the other is undefined; copying a config and deleting a line; spreading partial options objects.","solutions":["Always pass both targetType and targetId together","Remove both if the experiment is intentionally target-less (then don't pass scorers either)","Coalesce partial option objects so both keys are present or both absent"],"exampleFix":"// before\nawait dataset.createExperiment({ targetType: 'agent' });\n// after\nawait dataset.createExperiment({ targetType: 'agent', targetId: 'myAgent' });","handlingStrategy":"validation","validationCode":"function validateTargetArgs(args?: { targetType?: string; targetId?: string }): void {\n  const hasType = args?.targetType !== undefined;\n  const hasId = args?.targetId !== undefined;\n  if (hasType !== hasId) throw new Error('targetType and targetId must be provided together');\n}","typeGuard":"function hasCompleteTarget(args?: { targetType?: string; targetId?: string }): args is { targetType: string; targetId: string } & typeof args { return args?.targetType !== undefined && args?.targetId !== undefined; }","tryCatchPattern":"try {\n  await dataset.createExperiment(args);\n} catch (e) {\n  if (isMastraError(e) && e.id === 'EXPERIMENT_INVALID_TARGET') {\n    console.error('Supply targetType and targetId together (or neither)');\n  } else throw e;\n}","preventionTips":["Build target args with a helper that always sets both fields","Avoid conditionally setting only one of the pair in config objects","Type experiment options so the target is a single { targetType, targetId } object"],"tags":["storage","experiment","validation","invalid-arguments"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}