# How to Debug Export Functionality Issues in the Design.md CLI

> Debug Design.md CLI export issues by inspecting DesignSystemState and toggling emitters. Resolve invalid tokens, malformed dimensions, and emitter validation failures for smooth exports.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: how-to-guide
- Published: 2026-07-02

---

**Export issues in the Design.md CLI typically stem from invalid token names, malformed dimension objects, or emitter validation failures in the Tailwind emitter handlers, which can be isolated by inspecting the intermediate `DesignSystemState` and toggling between the default and v4 emitters.**

The Design.md CLI transforms DESIGN.md files into Tailwind-compatible CSS or JSON through a pure functional pipeline. When the export functionality fails or produces unexpected output, the issue usually originates in the **Tailwind emitter** handlers or the underlying model construction. Understanding the exact failure point—from token validation to dimension serialization—allows you to debug export functionality issues efficiently without guessing.

## Understanding the Export Architecture

The export flow follows a strict sequence of pure, side-effect-free transformations:

```

read DESIGN.md → parse → model → emitter → formatOutput → stdout

```

Each layer has distinct responsibilities:

- **CLI Entry Point** ([`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts)): The `formatOutput` function selects the appropriate exporter based on CLI flags and formats the final result as JSON or Markdown.

- **Model Handler** ([`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts)): Constructs the `DesignSystemState` (defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts)) by normalizing raw tokens into maps of colors, typography, and dimensions.

- **Tailwind Emitter** ([`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts)): The `TailwindEmitterHandler` class executes a pure function that maps `DesignSystemState` → Tailwind `theme.extend` JSON.

- **Tailwind v4 Emitter** ([`packages/cli/src/linter/tailwind/v4/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/v4/handler.ts)): The `TailwindV4EmitterHandler` provides stricter token validation against CSS identifier rules (`/^[a-zA-Z0-9][a-zA-Z0-9-]*$/`).

Failures surface only during **model construction** (invalid token syntax) or **emitter validation** (illegal CSS identifiers), making systematic isolation straightforward.

## Common Export Failure Points and Solutions

### "Token name … is not a valid CSS identifier"

This error originates in the **Tailwind v4 emitter**, which validates token names against strict CSS identifier rules.

**Debugging steps:**

1. Run the CLI with the default (non-v4) emitter to confirm the validation is the blocker: `design-md export --format json --emitter tailwind`
2. If the error disappears, inspect the offending token by printing the model: `design-md lint --format json | jq '.findings[] | select(.message|contains("valid CSS"))'`
3. Check the `state.colors`, `state.typography`, or other maps in the intermediate output.

### Missing Color or Spacing Entries

When the output JSON lacks expected design tokens, the **ModelHandler** likely filtered them due to parsing errors (e.g., malformed hex colors).

**Debugging steps:**

1. Enable verbose logging: `DEBUG=design-md:* design-md export`
2. Examine [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts) around line 271 where `parseColor` is called to see where entries might be dropped.

### Empty Output `{}`

If `formatOutput` produces an empty object, the emitter returned an empty `data` object despite `success:true`.

**Debugging steps:**

1. Add a temporary `console.log` in `TailwindEmitterHandler.execute` (line 23 in [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts)) to dump the full `state` object before mapping occurs.
2. Verify that `state.colors` and `state.spacing` contain entries after model construction.

### Unexpected Unit Strings (e.g., `1pxpx`)

Malformed dimension objects cause the `dimToString` serializer to produce invalid CSS values.

**Debugging steps:**

1. Inspect `mapDimensions` in [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts) (lines 72-77).
2. Validate the source of `state.spacing` and `state.rounded` by printing these maps before the mapping loop executes.

## Step-by-Step Debugging Guide

Follow this sequence to isolate export failures:

1. **Reproduce the issue locally** – Run the exact export command reported: `design-md export path/to/DESIGN.md --format json`

2. **Enable internal diagnostics** – Set the `DEBUG` environment variable to the `design-md:*` namespace to see model-level logs: `DEBUG=design-md:* design-md export ...`

3. **Inspect the parsed model** – Dump the intermediate `DesignSystemState` as JSON to examine raw token values: `design-md parse path/to/DESIGN.md --format json > state.json`

4. **Validate token names** – If using Tailwind v4, compare behavior against the legacy emitter: `design-md export --emitter tailwind` (non-v4) versus `design-md export --emitter tailwind-v4`

5. **Add temporary console statements** – Edit [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts) to log intermediate maps: `console.log('Colors map:', state.colors);`

6. **Run the unit tests** – Execute the test suite to isolate regressions: `npm test` or `bun test`, paying attention to [`tailwind/handler.test.ts`](https://github.com/google-labs-code/design.md/blob/main/tailwind/handler.test.ts) and [`tailwind/v4/fixture.test.ts`](https://github.com/google-labs-code/design.md/blob/main/tailwind/v4/fixture.test.ts)

7. **Check version compatibility** – Verify your CLI version matches the latest spec. The `VERSION` export in [`packages/cli/src/version.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/version.ts) (line 31) and [`packages/cli/package.json`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/package.json) define the expected schema support.

## Practical Code Examples for Debugging

### Minimal Reproduction Script

Print the raw model and final Tailwind JSON programmatically:

```typescript
import { readInput } from './utils.js';
import { ModelHandler } from './linter/model/handler.js';
import { TailwindEmitterHandler } from './linter/tailwind/handler.js';
import { formatOutput } from './utils.js';

async function debugExport(file: string) {
  const src = await readInput(file);
  const model = new ModelHandler().execute(src);
  console.log('=== Model ===', model);
  const emit = new TailwindEmitterHandler().execute(model);
  console.log('=== Tailwind JSON ===', formatOutput(emit, { format: 'json' }));
}

debugExport('examples/totality-festival/DESIGN.md');

```

### Quick Token Validation Check

Test the v4 emitter with explicit error handling:

```typescript
import { TailwindV4EmitterHandler } from './linter/tailwind/v4/handler.js';

try {
  const result = new TailwindV4EmitterHandler().execute(state);
  console.log('Export succeeded', result);
} catch (e) {
  console.error('Export validation failed', e);
}

```

### Force Non-v4 Emitter via CLI

Bypass strict validation when testing:

```bash
design-md export path/to/DESIGN.md --emitter tailwind      # default, permissive

design-md export path/to/DESIGN.md --emitter tailwind-v4   # strict validation

```

## Key Source Files Reference

| File | Role |
|------|------|
| [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts) | Formats CLI output (JSON/Markdown) and reads input files; contains `formatOutput` |
| [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts) | Defines `DesignSystemState` type and associated interfaces |
| [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts) | Constructs `DesignSystemState` from parsed DESIGN.md; contains `parseColor` logic around line 271 |
| [`packages/cli/src/linter/tailwind/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/spec.ts) | Declares `TailwindEmitterSpec` contract |
| [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts) | Core export implementation; `TailwindEmitterHandler.execute` at line 23, `mapDimensions` at lines 72-77 |
| [`packages/cli/src/linter/tailwind/v4/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/v4/handler.ts) | Strict v4 emitter with CSS identifier validation |
| [`packages/cli/src/version.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/version.ts) | Provides `VERSION` constant for compatibility checks |

## Summary

- Export failures originate in either **model construction** (`ModelHandler`) or **emitter validation** (`TailwindEmitterHandler`/`TailwindV4EmitterHandler`).
- Use `DEBUG=design-md:*` to enable verbose logging during the export process.
- Toggle between `--emitter tailwind` and `--emitter tailwind-v4` to isolate CSS identifier validation errors.
- Inspect the intermediate `DesignSystemState` by dumping the model output before it reaches the emitter handlers.
- Check [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts) lines 23 and 72-77 when debugging empty outputs or malformed dimension strings.

## Frequently Asked Questions

### Why does my Tailwind v4 export fail with "Token name is not a valid CSS identifier"?

The **TailwindV4EmitterHandler** enforces strict naming rules against the regex `/^[a-zA-Z0-9][a-zA-Z0-9-]*$/`. Token names containing spaces, special characters, or leading hyphens trigger this validation error. Run the export with `--emitter tailwind` (non-v4) to bypass this check, or rename the offending tokens in your DESIGN.md file to match valid CSS identifier syntax.

### How do I enable debug logging for the Design.md CLI?

Set the `DEBUG` environment variable to `design-md:*` before running your command: `DEBUG=design-md:* design-md export path/to/DESIGN.md`. This outputs internal logs from the model handler and emitter, revealing where tokens are parsed or dropped during the pipeline execution.

### Why are my colors missing from the exported JSON output?

Missing entries usually indicate that `parseColor` or similar validation logic in [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts) filtered malformed values during model construction. Use `design-md parse --format json` to inspect the raw `DesignSystemState` and verify that your color values use valid hex or RGB syntax recognized by the parser.

### What is the difference between the `tailwind` and `tailwind-v4` emitters?

The default **tailwind** emitter focuses on compatibility and exports tokens without strict CSS identifier validation. The **tailwind-v4** emitter adds a validation layer that ensures all token names conform to CSS grammar rules required by Tailwind CSS v4. If your design system uses legacy token names with spaces or special characters, use the default emitter or update your token names for v4 compatibility.