[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H8F5XZTKWNTPEBXRSPGKQ":3,"skill-same:01M71H8F5XZTKWNTPEBXRSPGKQ":51},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":29,"frontMatter":30,"refName":31,"commitSha":32,"skillDirectory":33,"forksCount":13,"repositoryHtmlUrl":34,"repositoryHomepageUrl":6,"ownerHtmlUrl":35,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":36,"install":37,"resources":50},"01M71H8F5XZTKWNTPEBXRSPGKQ","03-error-handling",null,"Effect-TS 4 error handling — Effect.catch, catchTag, catchTags, typed channels, and absorb patterns","lambda-solver\u002Flambdabench-pro","lambda-solver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F279071046?v=4","01M71H55W2WK3PM6RRAY9JZWAJ","01M71H55WRT9XAFDAVACTCC2XP",0,"MIT","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F03-error-handling\u002FSKILL.md",[],[18,19,20,21,22,23,24,25],"error","03 error handling","error handling","catch","effect","opencode","patterns","channels","2026-11-10 10:12:30",false,"---\nname: 03-error-handling\ndescription: Effect-TS 4 error handling — Effect.catch, catchTag, catchTags, typed channels, and absorb patterns\nlicense: MIT\ncompatibility: opencode\n---\n\n# Error Handling Patterns\n\n## Define errors at the module boundary\n\n```typescript\nimport { Schema } from \"effect\";\n\n\u002F\u002F Serializable tagged error — primary pattern\nexport class ParseError extends Schema.TaggedErrorClass\u003CParseError>()(\"ParseError\", {\n  input: Schema.String,\n  message: Schema.String,\n}) {}\n\n\u002F\u002F With unknown cause\nexport class FetchError extends Schema.TaggedErrorClass\u003CFetchError>()(\"FetchError\", {\n  url: Schema.String,\n  cause: Schema.Defect,\n}) {}\n\n\u002F\u002F Plain class — lightweight, non-serializable\nexport class LlmError {\n  readonly _tag = \"LlmError\";\n  constructor(readonly message: string) {}\n}\n```\n\n## catchTag \u002F catchTags — targeted recovery\n\n```typescript\n\u002F\u002F Single tag\nprogram.pipe(Effect.catchTag(\"ParseError\", (e) => Effect.succeed(`fallback: ${e.message}`)));\n\n\u002F\u002F Multiple tags — same handler\nprogram.pipe(Effect.catchTag([\"ParseError\", \"NetworkError\"], (_) => Effect.succeed(0)));\n\n\u002F\u002F Multiple tags — individual handlers\nprogram.pipe(\n  Effect.catchTags({\n    ParseError: (e) => Effect.succeed(`parse: ${e.message}`),\n    NetworkError: (e) => Effect.succeed(`net: ${e.statusCode}`),\n  }),\n);\n```\n\n## Effect.catch — all typed errors\n\n`Effect.catchAll` does **not exist** in Effect 4. Use `Effect.catch`.\nIt only catches recoverable (typed) errors — defects still propagate.\n\n```typescript\n\u002F\u002F ❌ Effect 3 — compile error in Effect 4\nprogram.pipe(Effect.catchAll((e) => Effect.succeed(\"fallback\")));\n\n\u002F\u002F ✅ Effect 4\nprogram.pipe(Effect.catch((_e) => Effect.succeed(\"fallback\")));\n```\n\n## Absorb boundary — unknown errors into typed channel\n\nWhen calling code that may fail with `unknown` (SDK errors, callbacks),\nuse `Effect.catch` to absorb into a safe fallback.\n\n```typescript\n\u002F\u002F LLM SDK may throw AiError or unknown — absorb at the boundary\nconst rawText =\n  yield *\n  LanguageModel.generateText({ prompt }).pipe(\n    Effect.map((r) => r.text),\n    Effect.catch((_e) => Effect.succeed(`@main = λf.λx.x  \u002F\u002F error: ${String(_e)}`)),\n  );\n```\n\n## Wrapping at service boundaries\n\nMap errors as they cross a layer boundary to keep the error type local.\n\n```typescript\nconst findById = Effect.fn(\"Repo.findById\")(function* (id: string) {\n  return yield* sql`SELECT * FROM users WHERE id = ${id}`.pipe(\n    Effect.mapError((cause) => new UserRepoError({ cause })),\n  );\n});\n```\n\n## Reason errors — nested categorized sub-errors\n\n```typescript\nexport class AiError extends Schema.TaggedErrorClass\u003CAiError>()(\n  \"AiError\",\n  { reason: Schema.Union([RateLimitError, QuotaExceededError, SafetyBlockedError]) },\n) {}\n\n\u002F\u002F Catch one reason\nprogram.pipe(\n  Effect.catchReason(\"AiError\", \"RateLimitError\",\n    (r) => Effect.succeed(`retry after ${r.retryAfter}s`),\n  ),\n)\n\n\u002F\u002F Unwrap into error channel\nprogram.pipe(\n  Effect.unwrapReason(\"AiError\"),\n  Effect.catchTags({\n    RateLimitError:    (r) => ...,\n    QuotaExceededError:(r) => ...,\n  }),\n)\n```\n\n## Catching defects (unexpected failures)\n\n```typescript\nimport { Cause } from \"effect\";\n\nprogram.pipe(\n  Effect.catchCause(\n    (cause) => (Cause.isFailure(cause) ? Effect.succeed(\"recovered\") : Effect.failCause(cause)), \u002F\u002F re-raise non-failure causes\n  ),\n);\n```\n\n## Return before yield\\* error\n\n```typescript\nexport const load = Effect.fn(\"load\")(function* (id: string) {\n  if (!id) return yield* new NotFoundError(); \u002F\u002F return stops TS inference here\n  return yield* fetchById(id);\n});\n```\n\n## Never fail silently\n\n```typescript\n\u002F\u002F ❌ swallows the error\n.pipe(Effect.catch((_) => Effect.succeed(undefined)))\n\n\u002F\u002F ✅ log then recover\n.pipe(\n  Effect.catch((e) =>\n    Effect.gen(function* () {\n      yield* Effect.logError(\"unexpected error\", e)\n      return defaultValue\n    }),\n  ),\n)\n```\n","# Error Handling Patterns\n\n## Define errors at the module boundary\n\n```typescript\nimport { Schema } from \"effect\";\n\n\u002F\u002F Serializable tagged error — primary pattern\nexport class ParseError extends Schema.TaggedErrorClass\u003CParseError>()(\"ParseError\", {\n  input: Schema.String,\n  message: Schema.String,\n}) {}\n\n\u002F\u002F With unknown cause\nexport class FetchError extends Schema.TaggedErrorClass\u003CFetchError>()(\"FetchError\", {\n  url: Schema.String,\n  cause: Schema.Defect,\n}) {}\n\n\u002F\u002F Plain class — lightweight, non-serializable\nexport class LlmError {\n  readonly _tag = \"LlmError\";\n  constructor(readonly message: string) {}\n}\n```\n\n## catchTag \u002F catchTags — targeted recovery\n\n```typescript\n\u002F\u002F Single tag\nprogram.pipe(Effect.catchTag(\"ParseError\", (e) => Effect.succeed(`fallback: ${e.message}`)));\n\n\u002F\u002F Multiple tags — same handler\nprogram.pipe(Effect.catchTag([\"ParseError\", \"NetworkError\"], (_) => Effect.succeed(0)));\n\n\u002F\u002F Multiple tags — individual handlers\nprogram.pipe(\n  Effect.catchTags({\n    ParseError: (e) => Effect.succeed(`parse: ${e.message}`),\n    NetworkError: (e) => Effect.succeed(`net: ${e.statusCode}`),\n  }),\n);\n```\n\n## Effect.catch — all typed errors\n\n`Effect.catchAll` does **not exist** in Effect 4. Use `Effect.catch`.\nIt only catches recoverable (typed) errors — defects still propagate.\n\n```typescript\n\u002F\u002F ❌ Effect 3 — compile error in Effect 4\nprogram.pipe(Effect.catchAll((e) => Effect.succeed(\"fallback\")));\n\n\u002F\u002F ✅ Effect 4\nprogram.pipe(Effect.catch((_e) => Effect.succeed(\"fallback\")));\n```\n\n## Absorb boundary — unknown errors into typed channel\n\nWhen calling code that may fail with `unknown` (SDK errors, callbacks),\nuse `Effect.catch` to absorb into a safe fallback.\n\n```typescript\n\u002F\u002F LLM SDK may throw AiError or unknown — absorb at the boundary\nconst rawText =\n  yield *\n  LanguageModel.generateText({ prompt }).pipe(\n    Effect.map((r) => r.text),\n    Effect.catch((_e) => Effect.succeed(`@main = λf.λx.x  \u002F\u002F error: ${String(_e)}`)),\n  );\n```\n\n## Wrapping at service boundaries\n\nMap errors as they cross a layer boundary to keep the error type local.\n\n```typescript\nconst findById = Effect.fn(\"Repo.findById\")(function* (id: string) {\n  return yield* sql`SELECT * FROM users WHERE id = ${id}`.pipe(\n    Effect.mapError((cause) => new UserRepoError({ cause })),\n  );\n});\n```\n\n## Reason errors — nested categorized sub-errors\n\n```typescript\nexport class AiError extends Schema.TaggedErrorClass\u003CAiError>()(\n  \"AiError\",\n  { reason: Schema.Union([RateLimitError, QuotaExceededError, SafetyBlockedError]) },\n) {}\n\n\u002F\u002F Catch one reason\nprogram.pipe(\n  Effect.catchReason(\"AiError\", \"RateLimitError\",\n    (r) => Effect.succeed(`retry after ${r.retryAfter}s`),\n  ),\n)\n\n\u002F\u002F Unwrap into error channel\nprogram.pipe(\n  Effect.unwrapReason(\"AiError\"),\n  Effect.catchTags({\n    RateLimitError:    (r) => ...,\n    QuotaExceededError:(r) => ...,\n  }),\n)\n```\n\n## Catching defects (unexpected failures)\n\n```typescript\nimport { Cause } from \"effect\";\n\nprogram.pipe(\n  Effect.catchCause(\n    (cause) => (Cause.isFailure(cause) ? Effect.succeed(\"recovered\") : Effect.failCause(cause)), \u002F\u002F re-raise non-failure causes\n  ),\n);\n```\n\n## Return before yield\\* error\n\n```typescript\nexport const load = Effect.fn(\"load\")(function* (id: string) {\n  if (!id) return yield* new NotFoundError(); \u002F\u002F return stops TS inference here\n  return yield* fetchById(id);\n});\n```\n\n## Never fail silently\n\n```typescript\n\u002F\u002F ❌ swallows the error\n.pipe(Effect.catch((_) => Effect.succeed(undefined)))\n\n\u002F\u002F ✅ log then recover\n.pipe(\n  Effect.catch((e) =>\n    Effect.gen(function* () {\n      yield* Effect.logError(\"unexpected error\", e)\n      return defaultValue\n    }),\n  ),\n)\n```\n",{"name":5,"license":14,"description":7,"compatibility":23},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b","reference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F03-error-handling","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro","https:\u002F\u002Fgithub.com\u002Flambda-solver","2026-05-31 17:08:46",{"source":8,"skillName":5,"commands":38,"prompt":48,"zipAvailable":49},[39,42,45],{"tool":40,"command":41},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 03-error-handling",{"tool":43,"command":44},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 03-error-handling",{"tool":46,"command":47},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 03-error-handling","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F03-error-handling\u002FSKILL.md",true,[],[52,83,104,123,144,162],{"skillNo":53,"name":54,"nameZh":6,"description":55,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":56,"categories":57,"keywords":63,"publishedAt":26},"01M71H9FNA5D6Y4ANXD18Z1Z3X","tmux-workflow","Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Ftmux\u002FSKILL.md",[58],{"categoryNo":59,"categoryName":60,"taxonomyType":61,"taxonomyTypeDesc":62},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[64,65,66,67,68,69,70,71,72,73,74,23,75,76,77,78,79,80,81,82],"tmux","workflow","tmux workflow","chat","dev servers","background","processes","storybook","live","servers","run","with","logs","development workflow","free","dev","sessions","for","development",{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":92,"publishedAt":26},"01M71H9DQJDAJVZX37NDN99D3P","04-anti-patterns","React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns\u002FSKILL.md",[89],{"categoryNo":90,"categoryName":91,"taxonomyType":61,"taxonomyTypeDesc":62},"01JBSEEDCAT000000000000009","前端开发",[24,93,94,95,96,97,98,99,100,101,102,23,103],"anti patterns","04 anti patterns","common","jsx","reference","conditional","hooks","manual","performance","anti-patterns","react",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":111,"publishedAt":26},"01M71H9BXF511W2R3B73S5P9ZN","03-state-management","React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState\u002FuseReducer","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F03-state-management\u002FSKILL.md",[110],{"categoryNo":90,"categoryName":91,"taxonomyType":61,"taxonomyTypeDesc":62},[112,113,114,115,103,116,24,117,118,119,120,23,121,75,122],"management","state management","state","03 state management","query","URL","tanstack","react state management","local","server","tanstack query",{"skillNo":124,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":130,"publishedAt":26},"01M71H9AAGVWMYQ4NG82QPYCTE","02-component-composition","React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",[129],{"categoryNo":90,"categoryName":91,"taxonomyType":61,"taxonomyTypeDesc":62},[131,132,133,23,75,134,135,103,136,24,137,138,139,140,141,142,143],"02 component composition","component","Composition","compound","components","primitives","composition patterns","list","map","rendering","render","react component","layout",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":151,"publishedAt":26},"01M71H98RDXRQZDR496SRD906M","01-fp-style","React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F01-fp-style\u002FSKILL.md",[150],{"categoryNo":90,"categoryName":91,"taxonomyType":61,"taxonomyTypeDesc":62},[152,153,154,24,155,156,23,157,103,158,135,99,159,160,161,22],"01 fp style","style","atom","conventions","integration","functional","programming","Tailwind","tailwind patterns","functional programming",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":169,"publishedAt":26},"01M71H95PYGAWBS5C8KN0C4WGT","react-animation","React animation with react\u002Fmotion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fanimation\u002FSKILL.md",[168],{"categoryNo":90,"categoryName":91,"taxonomyType":61,"taxonomyTypeDesc":62},[103,170,171,101,172,23,143,173,174,75,175,176,177,178],"react animation","Animation","framer motion","motion","best practices","framer","gestures","animations","declarative"]