gastownhall/beads · error

reading types.custom: %w

Error message

reading types.custom: %w

What it means

flattenUnregisteredIssueTypes determines which issue types in a cloned subgraph are unknown, by reading the registered custom types from config key 'types.custom' via s.GetConfig. If that read fails, the function refuses to assume 'nothing is registered' (which would silently flatten legitimately registered custom types) and instead throws 'reading types.custom: %w'. This is a deliberate fail-loud guard against data loss.

Source

Thrown at cmd/bd/template.go:609

		t := issue.IssueType
		if t == "" || t.IsBuiltIn() {
			continue
		}
		unknown[t] = true
	}
	if len(unknown) == 0 {
		return nil
	}

	// Match insert validation's sources: the types.custom config value
	// (kept in step with the custom_types table by SyncConfigTables)
	// overlaid with config.yaml-declared types. Read through s so a
	// transaction-bound caller sees in-transaction registration.
	existing, err := s.GetConfig(ctx, "types.custom")
	if err != nil {
		// Don't degrade to "nothing registered": a transient read failure
		// would silently flatten types the operator did register.
		return fmt.Errorf("reading types.custom: %w", err)
	}
	for _, t := range issueops.ParseTypesConfigValue(existing) {
		delete(unknown, types.IssueType(t))
	}
	for _, t := range config.GetCustomTypesFromYAML() {
		delete(unknown, types.IssueType(t))
	}
	if len(unknown) == 0 {
		return nil
	}

	names := make([]string, 0, len(unknown))
	for t := range unknown {
		names = append(names, string(t))
	}
	sort.Strings(names)
	WarnError("flattening unregistered issue type(s) to task (epic for steps with children): %s (register with bd config set types.custom to keep them)", strings.Join(names, ", "))

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error from errors.Unwrap and fix the underlying config-read failure.
  2. Run `bd doctor` to check storage/config health.
  3. Retry the clone once storage is responsive.
  4. Declare the custom types in config.yaml so cloning works even when custom-type registration must be re-created.

Example fix

// config.yaml
issue-types:
  custom:
    - molecule
    - gate
// ensures types resolve even if types.custom registration needs rebuild
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := s.GetConfig(ctx, "types.custom"); err != nil {
	return fmt.Errorf("cannot read registered types, aborting clone: %w", err)
}

Try / catch

err := flattenUnregisteredIssueTypes(ctx, tx, issues)
if err != nil && strings.HasPrefix(err.Error(), "reading types.custom") {
	// do NOT proceed: proceeding would flatten registered custom types
	return err
}

Prevention

When it happens

Trigger: Calling cloneSubgraphInto (or flattenUnregisteredIssueTypes directly, as in TestFlattenUnregisteredIssueTypes) when s.GetConfig(ctx, "types.custom") errors — transaction-bound reads failing, storage driver errors, or config store corruption.

Common situations: Dolt storage read failure mid-transaction; a broken or unreadable config table after an interrupted migration; embedded driver I/O errors.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d46f1fb9b5d725ca. Report an issue: GitHub.