Skip to content

Validation

Source: packages/core/src/core/monitoring/validation.ts, packages/core/src/core/monitoring/event-validation.ts, packages/core/src/core/errors.ts

validateConfig

typescript
function validateConfig(config: Journey, allJourneys?: Journey[]): void;

Validates a journey configuration. Performs Zod schema validation first, then structural checks for bounce chances, time spans, suppression periods, and duplicate IDs. When allJourneys is provided, also validates cross-journey references and detects circular dependencies.

Throws ZodError for schema failures or SynodeError for structural issues.

typescript
import { validateConfig } from '@synode/core';

// Single journey
validateConfig(journey);

// Cross-journey validation
validateConfig(purchaseJourney, [browseJourney, purchaseJourney]);

dryRun

typescript
async function dryRun(journey: Journey, userCount?: number): Promise<Event[]>;

Validates the journey, then generates events for userCount users (default: 1) and returns them in memory. Useful for quick smoke tests without configuring an adapter.

typescript
import { dryRun } from '@synode/core';

const events = await dryRun(journey, 3);
console.log(`Generated ${events.length} events for 3 users`);

SynodeError

Structured error class for all Synode validation and runtime errors. Extends Error.

typescript
class SynodeError extends Error {
  readonly code: ErrorCode;
  readonly path: string[];
  readonly suggestion: string | undefined;
  readonly rawMessage: string;
  readonly expected: string | undefined;
  readonly received: string | undefined;

  constructor(options: SynodeErrorOptions);
  format(): string;
}

format()

Returns a structured multi-line representation:

[INVALID_BOUNCE_CHANCE] Bounce chance must be between 0 and 1
  Path: Journey 'Purchase Flow' > Adventure 'Checkout'
  Expected: 0 <= bounceChance <= 1
  Received: 1.5
  Fix: Use a decimal like 0.3, not 30

SynodeErrorOptions

typescript
interface SynodeErrorOptions {
  code: ErrorCode;
  message: string;
  path: string[];
  suggestion?: string;
  expected?: string;
  received?: string;
  cause?: unknown;
}

ErrorCode

Union type of all 13 error codes:

CodeThrown when
INVALID_BOUNCE_CHANCEBounce chance is outside 0-1 range
INVALID_TIME_SPANTimeSpan min exceeds max
INVALID_SUPPRESSION_PERIODSuppression period min exceeds max
UNKNOWN_JOURNEY_REFrequires references a non-existent journey
CIRCULAR_DEPENDENCYJourney prerequisites form a cycle
DUPLICATE_IDSame ID used twice in adventures or actions
DATASET_NOT_FOUNDctx.dataset() called with unregistered ID
DATASET_EMPTYDataset has zero rows when a row is requested
HANDLER_ERRORUnhandled exception inside an action handler
ADAPTER_WRITE_ERROROutputAdapter.write() threw during output
INVALID_HANDLER_RETURNAction handler returned non-array value
TYPO_DETECTEDFuzzy match found a likely typo in an identifier
INVALID_DATASET_COUNTDataset count is negative, non-finite, or > 10M

SynodeValidationError

Error thrown when an event fails schema validation in strict mode. Extends Error.

typescript
class SynodeValidationError extends Error {
  readonly event: Event;
  readonly issues: ValidationIssue[];

  constructor(options: SynodeValidationErrorOptions);
}

interface ValidationIssue {
  path: (string | number)[];
  message: string;
  code: string;
}

ValidationSummary

Aggregate summary of event validation results, accumulated during generation.

typescript
interface ValidationSummary {
  eventsValidated: number;
  eventsValid: number;
  eventsInvalid: number;
  validationErrors: { eventName: string; path: string; message: string }[];
}

Errors are capped at 50 entries. Created internally by createValidationSummary().

defineEventSchema

typescript
function defineEventSchema<T extends z.ZodRawShape>(shape: T): z.ZodObject<T>;

Convenience wrapper around z.object() for defining event payload schemas.

typescript
import { z } from 'zod';
import { defineEventSchema } from '@synode/core';

const addToCartSchema = defineEventSchema({
  productId: z.string(),
  quantity: z.number().int().positive(),
  price: z.number().positive(),
});