From ad2bd673c407407cc4437fff8b6f01a3fc6f2e41 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 26 Dec 2025 02:04:56 +0900 Subject: [PATCH] fix: show error messages when oh-my-opencode.json config fails to load (#242) * fix: show error messages when oh-my-opencode.json config fails to load - Add console.error output for config parse errors (syntax errors) - Add console.error output for config validation errors (schema violations) - Display helpful hints for JSON syntax errors - List all validation errors clearly with proper formatting - Errors now shown immediately regardless of hook configuration Fixes #241 * refactor: replace console.error with toast notifications for config errors - Replace console.error with ctx.client.tui.showToast() for better UX - Show toast notifications for both syntax errors and validation errors - Toast notifications persist for 10 seconds for visibility - Display error details with bullet points for validation errors - Include helpful hints for JSON syntax errors This provides a more user-friendly notification system that integrates with OpenCode's UI instead of just logging to console. --------- Co-authored-by: sisyphus-dev-ai --- src/index.ts | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index e98d8ab..d31a498 100644 --- a/src/index.ts +++ b/src/index.ts @@ -116,7 +116,7 @@ function migrateConfigFile(configPath: string, rawConfig: Record `${i.path.join(".")}: ${i.message}`).join(", "); log(`Config validation error in ${configPath}:`, result.error.issues); addConfigLoadError({ path: configPath, error: `Validation error: ${errorMsg}` }); + + const errorList = result.error.issues + .map(issue => `• ${issue.path.join(".")}: ${issue.message}`) + .join("\n"); + + ctx.client.tui.showToast({ + body: { + title: "❌ OhMyOpenCode: Config Validation Failed", + message: `Failed to load ${configPath}\n\nValidation errors:\n${errorList}\n\nConfig will be ignored. Please fix the errors above.`, + variant: "error" as const, + duration: 10000, + }, + }).catch(() => {}); + return null; } @@ -140,6 +154,19 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null { const errorMsg = err instanceof Error ? err.message : String(err); log(`Error loading config from ${configPath}:`, err); addConfigLoadError({ path: configPath, error: errorMsg }); + + const hint = err instanceof SyntaxError + ? "\n\nHint: Check for syntax errors in your JSON file (missing commas, quotes, brackets, etc.)" + : ""; + + ctx.client.tui.showToast({ + body: { + title: "❌ OhMyOpenCode: Config Load Failed", + message: `Failed to load ${configPath}\n\nError: ${errorMsg}${hint}\n\nConfig will be ignored. Please fix the error above.`, + variant: "error" as const, + duration: 10000, + }, + }).catch(() => {}); } return null; } @@ -174,7 +201,7 @@ function mergeConfigs( }; } -function loadPluginConfig(directory: string): OhMyOpenCodeConfig { +function loadPluginConfig(directory: string, ctx: any): OhMyOpenCodeConfig { // User-level config path (OS-specific) const userConfigPath = path.join( getUserConfigDir(), @@ -190,10 +217,10 @@ function loadPluginConfig(directory: string): OhMyOpenCodeConfig { ); // Load user config first (base) - let config: OhMyOpenCodeConfig = loadConfigFromPath(userConfigPath) ?? {}; + let config: OhMyOpenCodeConfig = loadConfigFromPath(userConfigPath, ctx) ?? {}; // Override with project config - const projectConfig = loadConfigFromPath(projectConfigPath); + const projectConfig = loadConfigFromPath(projectConfigPath, ctx); if (projectConfig) { config = mergeConfigs(config, projectConfig); } @@ -209,7 +236,7 @@ function loadPluginConfig(directory: string): OhMyOpenCodeConfig { } const OhMyOpenCodePlugin: Plugin = async (ctx) => { - const pluginConfig = loadPluginConfig(ctx.directory); + const pluginConfig = loadPluginConfig(ctx.directory, ctx); const disabledHooks = new Set(pluginConfig.disabled_hooks ?? []); const isHookEnabled = (hookName: HookName) => !disabledHooks.has(hookName);