---
title: Troubleshooting
description: Solutions for common errors and problems with go-minitrace
doc_version: 1
last_updated: 2026-07-02
---


This page collects solutions for common errors and unexpected behavior when using go-minitrace.

## Conversion errors

### unsupported Codex format hint: unknown-jsonl

**What happened**: The Codex converter encountered a session file with a JSONL format it does not recognize.

**Cause**: Older Codex sessions or sessions from a different Codex version may use a format the adapter has not been taught to parse.

**Solution**: This is a known limitation. The converter currently fails on the first unrecognized session rather than skipping it. There is no workaround other than removing the problematic session file from the Codex directory before conversion.

### Empty output after conversion

**What happened**: The convert command ran without errors but produced no minitrace files.

**Cause**: The source directory does not contain files matching the expected patterns, or the directory path is wrong.

**Solution**: Run `discover` first to confirm sessions exist:

```bash
go-minitrace discover claude-code --output json | jq length
```

If discover reports 0 sessions, check the `--source-dir` path.

### Permission denied reading source files

**What happened**: The converter cannot read session files.

**Cause**: Session files are owned by a different user or have restrictive permissions.

**Solution**: Check file ownership with `ls -la` on the source directory. If needed, adjust permissions or run as the appropriate user.

### Very large number of output files

**What happened**: Converting Claude Code produced many more files than expected.

**Cause**: Claude Code subagent sessions each become their own minitrace file. A session that delegates to 10 subagents produces 11 files (1 main + 10 subagent).

**Solution**: This is expected behavior. Filter subagent sessions in queries:

```sql
WHERE (provenance->>'source_format') NOT LIKE '%subagent%'
```

## Query errors

### TypeError: Cannot mix BigInt and other types

**What happened**: A JS command handler threw `TypeError: Cannot mix BigInt and other types, use explicit conversions`.

**Cause**: DuckDB `SUM()` over integers returns `*big.Int` in Go, which Goja maps to JS `BigInt`. BigInt cannot participate in arithmetic with JS `Number`.

**Solution (v0.4+)**: Upgrade to go-minitrace v0.4 or later. `NormalizeValue()` now converts `*big.Int` → `int64` and `duckdb.Decimal` → `float64` before values reach Goja, eliminating this error entirely.

**Solution (pre-v0.4)**: Wrap all numeric query results in `Number()` before using them in JS arithmetic:

```js
const total = Number(r.total_calls);
const success = Number(r.success_count);
const rate = total > 0 ? (success / total * 100).toFixed(1) + "%" : "N/A";
```

See also: `go-minitrace help js-api-reference` — BigInt handling section.

### Conversion Error: Failed to cast value to numerical when using ->>

**What happened**: A SQL query using `tc->>'tool_name'` or `tc->'input'->>'command'` on an UNNESTed tool_calls column throws:

```
Conversion Error: Failed to cast value to numerical: {"id":"toolu_...","emitting_t...}
```

**Cause**: The `tc` column produced by `UNNEST(tool_calls) AS t(tc)` may be a DuckDB struct rather than a JSON string. Arrow operators (`->>`) on a struct attempt to cast the struct to a number, which fails.

**Solution**: Use `json_extract_string()` instead of arrow operators on UNNESTed elements:

```sql
-- WRONG: arrow operators on struct
SELECT tc->>'tool_name' FROM sessions_base, UNNEST(tool_calls) AS t(tc)

-- RIGHT: json_extract_string on struct
SELECT json_extract_string(tc, '$.tool_name') FROM sessions_base, UNNEST(tool_calls) AS t(tc)
```

Which representation you get (struct vs JSON) depends on the DuckDB version and how the archive was loaded. The `json_extract_string()` function works in both cases; arrow operators only work when the column is a JSON string.

### Accessing bash command text in tool_calls

**What happened**: You want to query the shell command from bash tool calls, but `tc->'input'->>'command'` returns NULL.

**Cause**: Pi's bash tool stores the command in `input.arguments.command`, not `input.command`. Other tools use `input.file_path` or `input.command`. The exact path varies by adapter.

**Solution**: Inspect a sample tool call first to find the right JSON path:

```sql
SELECT tc FROM sessions_base, UNNEST(tool_calls) AS t(tc)
WHERE json_extract_string(tc, '$.tool_name') = 'bash'
LIMIT 1
```

Then use the correct path. For Pi sessions:

```sql
SELECT json_extract_string(tc, '$.input.arguments.command') AS cmd
FROM sessions_base, UNNEST(tool_calls) AS t(tc)
WHERE json_extract_string(tc, '$.tool_name') = 'bash'
  AND json_extract_string(tc, '$.input.arguments.command') ILIKE '%remarquee%'
```

For a safe fallback that works across adapters:

```sql
SELECT COALESCE(
  json_extract_string(tc, '$.input.command'),
  json_extract_string(tc, '$.input.arguments.command')
) AS cmd
FROM sessions_base, UNNEST(tool_calls) AS t(tc)
WHERE json_extract_string(tc, '$.tool_name') = 'bash'
```

### Query returns 0 rows

**What happened**: A query ran successfully but returned no results.

**Cause**: The `--archive-glob` pattern does not match any files, or the WHERE clause filters everything out.

**Solution**: First verify loading with `--load-only`:

```bash
go-minitrace query duckdb \
  --archive-glob './output/active/*/*.minitrace.json' \
  --load-only
```

If this returns 0, check the glob path with `ls`:

```bash
ls ./output/active/*/*.minitrace.json | head
```

### no query source specified

**What happened**: The query command exited with this error.

**Cause**: None of `--preset`, `--sql`, `--sql-file`, or `--load-only` was specified.

**Solution**: Add one of the four query mode flags:

```bash
go-minitrace query duckdb --archive-glob '...' --preset session-list
```

### preset, sql, and sql-file are mutually exclusive

**What happened**: The command rejected the flag combination.

**Cause**: More than one query mode was specified.

**Solution**: Use exactly one of `--preset`, `--sql`, or `--sql-file`.

### Type errors in custom SQL

**What happened**: DuckDB reports a type error or unexpected NULL values.

**Cause**: JSON extraction with `->>` always returns strings. Doing arithmetic on a string fails.

**Solution**: Wrap in `CAST`:

```sql
-- Wrong: comparing string to number
WHERE metrics->>'turn_count' > 10

-- Right: cast first
WHERE CAST(metrics->>'turn_count' AS INT) > 10
```

### UNNEST returns no rows

**What happened**: A query using `UNNEST(tool_calls)` or `UNNEST(turns)` produces no output.

**Cause**: All matched sessions have empty arrays for the unnested column, or your WHERE clause filters out all unnested rows.

**Solution**: Check that your filter includes sessions that actually have tool calls or turns:

```sql
SELECT id, CAST(metrics->>'tool_call_count' AS INT) AS tools
FROM sessions_base
WHERE CAST(metrics->>'tool_call_count' AS INT) > 0
LIMIT 5;
```

If you are filtering on unnested tool-call fields, first verify the raw distribution without the extra WHERE clause:

```sql
SELECT tc->>'tool_name' AS tool, COUNT(*) AS uses
FROM sessions_base,
     UNNEST(tool_calls) AS t(tc)
GROUP BY tool
ORDER BY uses DESC;
```

### DuckDB JSON[] sharp edges with tool_calls

**What happened**: `tool_calls` looks present in the archive, but ad hoc SQL still returns `NULL`, odd results, or parser/type errors.

**Cause**: `tool_calls`, `turns`, and `annotations` are loaded as DuckDB `JSON[]` columns. The most common problems are:

- using `tool_calls[0]` as if lists were zero-based
- applying JSON paths to the whole `tool_calls` container instead of unnested elements
- guessing the wrong nested input field (`input.path` vs `input.file_path` vs `input.arguments.path`)
- using `->` / `->>` inside predicates without parentheses (this shows up most often with `LIKE`, but the same habit is safer for `=`, `IN`, and `NOT LIKE` too)

**Solution**:

1. Prefer this pattern first:

```sql
SELECT tc->>'tool_name' AS tool
FROM sessions_base,
     UNNEST(tool_calls) AS t(tc)
LIMIT 20;
```

2. Remember that DuckDB list indexing is 1-based:

```sql
SELECT
  tool_calls[1]->>'tool_name' AS first_tool,
  tool_calls[0]->>'tool_name' AS zeroth_tool
FROM sessions_base
LIMIT 1;
```

3. For file-oriented tools, use a path fallback instead of assuming `input.path` exists:

```sql
SELECT
  COALESCE(tc->'input'->>'file_path', tc->'input'->'arguments'->>'path') AS path
FROM sessions_base,
     UNNEST(tool_calls) AS t(tc)
WHERE (tc->>'tool_name') IN ('read', 'write', 'edit')
LIMIT 20;
```

4. If you filter with a predicate, parenthesize the `->` / `->>` extraction:

```sql
WHERE (tc->'input'->>'command') LIKE '%docmgr%'
```

## Validation issues

### All files valid_json but queries fail

**What happened**: `validate` reports all files as valid JSON, but queries return unexpected results.

**Cause**: `validate` currently checks JSON syntax only, not schema compliance. Files can be valid JSON but have wrong or missing fields.

**Solution**: This is expected. Schema validation is planned for a future release. Check specific files manually if queries return unexpected data:

```bash
cat ./output/active/2026-03/abc123.minitrace.json | jq '.metrics'
```

## Discovery issues

### Discover is very slow

**What happened**: Discovery takes a long time to complete.

**Cause**: The source directory contains thousands of session files and the discovery walks the entire tree.

**Solution**: This is expected for large session stores. The discovery is read-only and will complete — it just takes time proportional to the number of files.

### Discover reports unexpected format hints

**What happened**: Discovery shows format hints you do not recognize.

**Cause**: The session files may be from a newer or older version of the source tool.

**Solution**: Check if your go-minitrace version supports the format. Update if needed:

```bash
go install github.com/go-go-golems/go-minitrace/cmd/go-minitrace@latest
```

## Performance

### Conversion is slow for large archives

**What happened**: Converting thousands of sessions takes a long time.

**Cause**: Each session file must be read, parsed, and written individually.

**Solution**: Convert in batches. For Claude Code, you can use separate source directories per project. For DuckDB queries, use `--db-path` with a file to avoid reloading on every query.

### Queries are slow on large archives

**What happened**: DuckDB queries take a long time.

**Cause**: Loading thousands of JSON files into DuckDB requires parsing each file.

**Solution**: Use a persistent database to avoid reloading:

```bash
go-minitrace query duckdb \
  --archive-glob '...' \
  --db-path analysis.duckdb \
  --persist-loaded \
  --load-only

# Now query without reloading
go-minitrace query duckdb \
  --db-path analysis.duckdb \
  --archive-glob '' \
  --sql "SELECT COUNT(*) FROM sessions_base"
```

## See also

- `go-minitrace help getting-started` — tutorial covering the basic workflow
- `go-minitrace help convert-commands` — conversion flags and per-adapter details
- `go-minitrace help query-commands` — query modes and flags
