summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMaciek Szczesniak <[email protected]>2026-01-15 18:53:06 +0100
committerGitHub <[email protected]>2026-01-15 11:53:06 -0600
commit37f30993fa933fc5c4b7f9de40d486e39b70070d (patch)
tree36c12d7306b929a459e2f84ea5485135e60c6ca4
parentebc194ca9a8725721da13db5e2024a411a99aa8c (diff)
downloadopencode-37f30993fa933fc5c4b7f9de40d486e39b70070d.tar.gz
opencode-37f30993fa933fc5c4b7f9de40d486e39b70070d.zip
fix: show toast error message on ConfigMarkdown parse error (#8049)
Co-authored-by: Aiden Cline <[email protected]>
-rw-r--r--packages/opencode/src/config/config.ts35
-rw-r--r--packages/opencode/src/skill/skill.ts18
2 files changed, 43 insertions, 10 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 06803879f..134358ec3 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -19,6 +19,8 @@ import { BunProc } from "@/bun"
import { Installation } from "@/installation"
import { ConfigMarkdown } from "./markdown"
import { existsSync } from "fs"
+import { Bus } from "@/bus"
+import { Session } from "@/session"
export namespace Config {
const log = Log.create({ service: "config" })
@@ -231,8 +233,15 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
- const md = await ConfigMarkdown.parse(item)
- if (!md.data) continue
+ const md = await ConfigMarkdown.parse(item).catch((err) => {
+ const message = ConfigMarkdown.FrontmatterError.isInstance(err)
+ ? `${err.data.path}: ${err.data.message}`
+ : `Failed to parse command ${item}`
+ Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
+ log.error("failed to load command", { command: item, err })
+ return undefined
+ })
+ if (!md) continue
const patterns = ["/.opencode/command/", "/.opencode/commands/", "/command/", "/commands/"]
const file = rel(item, patterns) ?? path.basename(item)
@@ -263,8 +272,15 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
- const md = await ConfigMarkdown.parse(item)
- if (!md.data) continue
+ const md = await ConfigMarkdown.parse(item).catch((err) => {
+ const message = ConfigMarkdown.FrontmatterError.isInstance(err)
+ ? `${err.data.path}: ${err.data.message}`
+ : `Failed to parse agent ${item}`
+ Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
+ log.error("failed to load agent", { agent: item, err })
+ return undefined
+ })
+ if (!md) continue
const patterns = ["/.opencode/agent/", "/.opencode/agents/", "/agent/", "/agents/"]
const file = rel(item, patterns) ?? path.basename(item)
@@ -294,8 +310,15 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
- const md = await ConfigMarkdown.parse(item)
- if (!md.data) continue
+ const md = await ConfigMarkdown.parse(item).catch((err) => {
+ const message = ConfigMarkdown.FrontmatterError.isInstance(err)
+ ? `${err.data.path}: ${err.data.message}`
+ : `Failed to parse mode ${item}`
+ Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
+ log.error("failed to load mode", { mode: item, err })
+ return undefined
+ })
+ if (!md) continue
const config = {
name: path.basename(item, ".md"),
diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts
index 1cc3afee9..95a599a54 100644
--- a/packages/opencode/src/skill/skill.ts
+++ b/packages/opencode/src/skill/skill.ts
@@ -1,4 +1,5 @@
import z from "zod"
+import path from "path"
import { Config } from "../config/config"
import { Instance } from "../project/instance"
import { NamedError } from "@opencode-ai/util/error"
@@ -7,6 +8,9 @@ import { Log } from "../util/log"
import { Global } from "@/global"
import { Filesystem } from "@/util/filesystem"
import { Flag } from "@/flag/flag"
+import { Bus } from "@/bus"
+import { TuiEvent } from "@/cli/cmd/tui/event"
+import { Session } from "@/session"
export namespace Skill {
const log = Log.create({ service: "skill" })
@@ -42,10 +46,16 @@ export namespace Skill {
const skills: Record<string, Info> = {}
const addSkill = async (match: string) => {
- const md = await ConfigMarkdown.parse(match)
- if (!md) {
- return
- }
+ const md = await ConfigMarkdown.parse(match).catch((err) => {
+ const message = ConfigMarkdown.FrontmatterError.isInstance(err)
+ ? `${err.data.path}: ${err.data.message}`
+ : `Failed to parse skill ${match}`
+ Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
+ log.error("failed to load skill", { skill: match, err })
+ return undefined
+ })
+
+ if (!md) return
const parsed = Info.pick({ name: true, description: true }).safeParse(md.data)
if (!parsed.success) return