Skip to content
Back to skills

Output Error Missing Schemas

ASecurity

Fix missing schema definitions in Output SDK steps. Use when seeing type errors, undefined properties at step boundaries, validation failures, or when step inputs/outputs aren't being properly typed.

  • 440 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
data-aitypescriptgobashapidocumentation

Works with

  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add growthxai/output --skill output-error-missing-schemas --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Output Error Missing Schemas?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Output Error Missing Schemas
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/growthxai-output-error-missing-schemas/badge)](https://www.skillsdirectory.com/skills/growthxai-output-error-missing-schemas)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: output-error-missing-schemas
description: Fix missing schema definitions in Output SDK steps. Use when seeing type errors, undefined properties at step boundaries, validation failures, or when step inputs/outputs aren't being properly typed.
allowed-tools: [Bash, Read]
---

# Fix Missing Schema Definitions

## Overview

This skill helps diagnose and fix issues caused by steps that lack explicit `inputSchema` or `outputSchema` definitions. Schemas are essential for type safety, validation, and proper data serialization between steps.

## When to Use This Skill

You're seeing:
- Type errors at step boundaries
- Undefined properties in step inputs/outputs
- Validation failures when passing data between steps
- TypeScript errors about incompatible types
- Runtime errors about unexpected data shapes

## Root Cause

Steps without explicit schemas:
- Don't validate input data at runtime
- Don't provide TypeScript type inference
- May serialize/deserialize data incorrectly
- Can pass undefined or malformed data silently

## Symptoms

### Missing Input Schema

```typescript
// WRONG: No input validation
export const processData = step( {
  name: 'processData',
  // inputSchema: missing!
  outputSchema: z.object( { result: z.string() } ),
  fn: async input => {
    return { result: input.value };  // input.value might be undefined!
  }
} );
```

### Missing Output Schema

```typescript
// WRONG: No output validation
export const fetchData = step( {
  name: 'fetchData',
  inputSchema: z.object( { id: z.string() } ),
  // outputSchema: missing!
  fn: async input => {
    return { data: await getFromApi( input.id ) };  // Output shape not validated
  }
} );
```

### Both Schemas Missing

```typescript
// WRONG: No validation at all
export const transformData = step( {
  name: 'transformData',
  // No schemas!
  fn: async input => {
    return transform( input );
  }
} );
```

## Solution

Always define both `inputSchema` and `outputSchema` for every step:

### Complete Step Definition

```typescript
import { z, step } from '@outputai/core';

export const processData = step( {
  name: 'processData',
  inputSchema: z.object( {
    id: z.string(),
    value: z.number(),
    optional: z.string().optional()
  } ),
  outputSchema: z.object( {
    result: z.string(),
    processedAt: z.number()
  } ),
  fn: async input => {
    // input is fully typed: { id: string, value: number, optional?: string }
    return {
      result: `Processed ${input.id}`,
      processedAt: Date.now()
    };
    // output is validated against outputSchema
  }
} );
```

## Schema Definition Best Practices

### Use Descriptive Schemas

```typescript
// Good: Clear, descriptive schema
inputSchema: z.object( {
  userId: z.string().uuid(),
  email: z.string().email(),
  age: z.number().int().positive()
} )
```

### Handle Optional Fields

```typescript
inputSchema: z.object( {
  required: z.string(),
  optional: z.string().optional(),
  withDefault: z.string().default( 'fallback' )
} )
```

### Use Schema Composition

```typescript
// Define reusable schemas
const userSchema = z.object( {
  id: z.string(),
  name: z.string()
} );

const addressSchema = z.object( {
  street: z.string(),
  city: z.string()
} );

// Compose in step
inputSchema: z.object( {
  user: userSchema,
  address: addressSchema
} )
```

### Handle Arrays and Nested Objects

```typescript
inputSchema: z.object( {
  items: z.array( z.object( {
    id: z.string(),
    quantity: z.number()
  } ) ),
  metadata: z.record( z.string() )
} )
```

## Finding Steps Without Schemas

Search your codebase:

```bash
# Find step definitions
grep -rn "step({" src/workflows/

# Look for steps without inputSchema
grep -A5 "step({" src/workflows/ | grep -B2 "fn:"

# Check if schemas are present
grep -rn "inputSchema:" src/workflows/
grep -rn "outputSchema:" src/workflows/
```

Review each step definition to ensure both schemas are present.

## Benefits of Explicit Schemas

1. **Runtime Validation**: Catches data errors early
2. **Type Safety**: Full TypeScript inference in step functions
3. **Documentation**: Schemas document expected data shapes
4. **Serialization**: Ensures proper data serialization between steps
5. **Error Messages**: Clear validation errors when data is wrong

## Common Schema Patterns

### API Response Steps

```typescript
export const fetchUser = step( {
  name: 'fetchUser',
  inputSchema: z.object( {
    userId: z.string()
  } ),
  outputSchema: z.object( {
    user: z.object( {
      id: z.string(),
      name: z.string(),
      email: z.string()
    } ).nullable(),  // Handle not found
    found: z.boolean()
  } ),
  fn: async input => {
    const user = await api.getUser( input.userId );
    return { user, found: user !== null };
  }
} );
```

### Transformation Steps

```typescript
export const transformData = step( {
  name: 'transformData',
  inputSchema: z.object( {
    raw: z.array( z.unknown() )
  } ),
  outputSchema: z.object( {
    processed: z.array( z.object( {
      id: z.string(),
      value: z.number()
    } ) ),
    count: z.number()
  } ),
  fn: async input => {
    const processed = input.raw.map( transformItem );
    return { processed, count: processed.length };
  }
} );
```

### Void Output Steps

For steps that don't return meaningful data:

```typescript
export const logEvent = step( {
  name: 'logEvent',
  inputSchema: z.object( {
    event: z.string(),
    data: z.record( z.unknown() )
  } ),
  outputSchema: z.object( {
    logged: z.literal( true )
  } ),
  fn: async input => {
    await logger.log( input.event, input.data );
    return { logged: true };
  }
} );
```

## Verification

After adding schemas:

1. **TypeScript check**: `npm run output:worker:build` should pass without type errors
2. **Runtime test**: `npx output workflow run <name> '<input>'` should validate correctly
3. **Invalid input test**: Pass invalid data and verify validation errors appear

## Related Issues

- For Zod import issues, see `output-error-zod-import`
- For type mismatches despite schemas, verify schema matches actual data

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.