Skip to content

Parsing issues within config #88

@ybw0014

Description

@ybw0014

Description

When aft.jsonc contains // line comments or /* */ block comments above object keys, comment-json@4.6.2 attaches Symbol.for(...) properties to the parsed result to track comment positions. AFT passes this object directly to AftConfigSchema.safeParse(rawConfig) (Zod), which iterates all own properties including Symbol keys. Zod attempts to convert these Symbol keys to strings for path construction and throws:

TypeError: Cannot convert a symbol to a string

This causes the entire config loading to fail silently (caught by the try/catch in loadConfigFromPath), resulting in search_index, semantic_search, and all other settings falling back to their defaults (disabled).

Expected Behavior

aft.jsonc with comments should load correctly, since comments are a core JSONC feature and AFT documentation states "Both files are JSONC (comments allowed)".

Steps to Reproduce

  1. Add any // comment above a key inside a nested object in aft.jsonc, e.g.:
    {
      "lsp": {
        "servers": {
          // My custom server
          "my-server": { "binary": "my-lsp" }
        }
      }
    }
  2. Restart OpenCode
  3. Check aft-plugin.log — error: Cannot convert a symbol to a string
  4. Check /aft-statussearch_index and semantic_search show as disabled

Root Cause

In packages/opencode-plugin/src/config.ts, loadConfigFromPath():

const rawConfig = parseJsonc<Record<string, unknown>>(content);  // attaches Symbol props
migrateRawConfig(rawConfig, configPath, { log, warn });
const result = AftConfigSchema.safeParse(rawConfig);  // Zod crashes on Symbol keys

comment-json.parse() returns objects with Symbol.for("before:<key>") properties. No cleanup is performed between parseJsonc and safeParse.

Suggested Fix

Strip Symbol properties before Zod validation. Options:

  1. Use comment-json built-in removeComments() before safeParse:
    const cleaned = removeComments(rawConfig);
    const result = AftConfigSchema.safeParse(cleaned);
  2. Manually strip Symbol keys with a recursive helper:
    function stripSymbols(obj: unknown): unknown {
      if (typeof obj !== "object" || obj === null) return obj;
      if (Array.isArray(obj)) return obj.map(stripSymbols);
      const out: Record<string, unknown> = {};
      for (const [k, v] of Object.entries(obj)) out[k] = stripSymbols(v);
      return out;
    }

Environment

  • AFT: v0.34.0
  • OS: macOS arm64 (darwin)
  • Node: v25.8.2
  • OpenCode: 1.15.13
  • comment-json: 4.6.2 (bundled)

Workaround

Remove all comments from aft.jsonc (use strict JSON format without // or /* */ comments).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions