{"id":28939713,"url":"https://github.com/yakdriver/smarterr","last_synced_at":"2025-07-04T12:02:02.557Z","repository":{"id":296443050,"uuid":"983732893","full_name":"YakDriver/smarterr","owner":"YakDriver","description":null,"archived":false,"fork":false,"pushed_at":"2025-06-19T22:55:01.000Z","size":157,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-23T00:47:31.907Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YakDriver.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-14T20:40:27.000Z","updated_at":"2025-06-19T22:18:50.000Z","dependencies_parsed_at":"2025-05-31T03:15:33.743Z","dependency_job_id":"bbad10a6-1d3c-4d41-b5a3-136fc8d3a61c","html_url":"https://github.com/YakDriver/smarterr","commit_stats":null,"previous_names":["yakdriver/smarterr"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/YakDriver/smarterr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YakDriver%2Fsmarterr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YakDriver%2Fsmarterr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YakDriver%2Fsmarterr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YakDriver%2Fsmarterr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YakDriver","download_url":"https://codeload.github.com/YakDriver/smarterr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YakDriver%2Fsmarterr/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261403040,"owners_count":23153207,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-23T00:40:04.327Z","updated_at":"2025-07-04T12:02:02.547Z","avatar_url":"https://github.com/YakDriver.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smarterr\n\n**Declarative, layered, and maintainable error messages for Go.**\n\nWith a single line of code:\n\n```go\nreturn smarterr.Append(ctx, diags, err, \"id\", \"r-1234567890\")\n```\n\nsmarterr uses configuration—not code changes—to split an incoming error into **three output channels**:\n\n1. **Error summary** (for users)\n\n   ```console\n   creating CloudWatch Composite Alarm\n   ```\n\n1. **Error detail with a suggested fix** (for users)\n\n   ```console\n   ID: r-1234567890\n   Cause: operation error CloudWatch: ModifyServerlessCache\n   If you are trying to modify a serverless cache, please use the\n   `aws_cloudwatch_serverless_cache` resource instead of\n   `aws_cloudwatch_log_group`.\n   ```\n\n1. **Log** ([`tflog`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-log/tflog) or Go log)\n\n   ```console\n   creating CloudWatch Composite Alarm (ID r-1234567890): operation error CloudWatch: ModifyServerlessCache, https response error StatusCode: 400, RequestID: 9c9c8b2c-d71b-4717-b62a-68cfa4b18aa9, InvalidParameterCombination: No\n   ```\n\n---\n\n**smarterr** lets you define, update, and standardize error output for thousands of call sites—using Config, not code. Evolve your error messages and formatting without cross-codebase refactors. Both developers and users get clean diagnostics.\n\n## smarterr: Library and command line interface\n\nsmarterr consists of two components:\n\n- **Go Library:** Integrate into your application or provider code to format errors, emit diagnostics, and control runtime logging.\n- **Command-Line Tool (CLI):** Use during development or CI to check configuration files and inspect merged output to catch issues.\n\n**Use the library** to power smarterr behavior at runtime.\n**Use the CLI** to debug and verify configs before they ship.\n\n---\n\n## Command-line installation\n\nYou can install the smarterr CLI with Go:\n\n```sh\ngo install github.com/YakDriver/smarterr/cmd/smarterr@latest\n```\n\nThis will install the `smarterr` binary in your `$GOPATH/bin` or `$HOME/go/bin`.\n\n---\n\n## GitHub action\n\nYou can use the [GitHub Action](https://github.com/marketplace/actions/check-smarterr-config) to check Config during CI checks.\n\nFor example:\n\n```yaml\n- uses: YakDriver/check-smarterr-config@latest\n  name: Check smarterr config\n  with:\n    base-dir: './internal'\n```\n\n## Template types and usage\n\nsmarterr supports two main template types for customizing diagnostic output:\n\n- **Error templates**: `error_summary` and `error_detail`\n  - Used when formatting diagnostics from Go errors (for example, via `AddError` or `Append`).\n- **Diagnostic templates**: `diagnostic_summary` and `diagnostic_detail`\n  - Used when enriching framework-generated diagnostics (for example, via `EnrichAppend`).\n\n\u003e **Note:** smarterr outputs diagnostics. The template name refers to the input type (error vs. diagnostic).\n\n**Function-to-template mapping:**\n\n- `AddError` and `Append` use `error_summary` and `error_detail`.\n- `EnrichAppend` uses `diagnostic_summary` and `diagnostic_detail`.\n\nsmarterr falls back to the original error or diagnostic content if you don't define templates.\n\n## Why smarterr\n\n- **For developers:**\n  - No more hunting down and updating error messages in thousands of places.\n  - Consistent, high-quality error output everywhere, driven by Config.\n  - Layered, declarative configuration—like you expect from modern tools—applied to error handling as a library.\n  - Evolve your error messages and formatting without cross-codebase refactors.\n- **For users:**\n  - Cleaner, more helpful, and consistent error messages.\n  - Easier to understand, context-aware diagnostics to act on.\n\n\u003e In a large project (like the Terraform AWS Provider, with ~15,000 error sites), smarterr lets you manage error output centrally and declaratively—an evolutionary step toward declarative development.\n\n---\n\n## Quickstart\n\n### Library usage\n\n1. **Embed your Config:**\n\n  ```go\n  //go:embed service/smarterr.hcl\n  //go:embed service/*/smarterr.hcl\n  var SmarterrFS embed.FS\n\n  var smarterrInitOnce sync.Once\n\n  func init() {\n    smarterrInitOnce.Do(func() {\n      smarterr.SetLogger(smarterr.TFLogLogger{})\n      smarterr.SetFS(\u0026smarterr.WrappedFS{FS: \u0026SmarterrFS}, \"dir/where/files/are/embedded/such/as/internal\")\n    })\n  }\n  ```\n\n1. **Call smarterr in your error handling:**\n\n   ```go\n   smarterr.AddError(ctx, diags, err, \"id\", id) // uses error_summary/error_detail\n   // or for SDK diagnostics:\n   diags = smarterr.Append(ctx, diags, err, \"id\", id) // uses error_summary/error_detail\n   // or to enrich framework diagnostics:\n   smarterr.EnrichAppend(ctx, \u0026diags, incoming, \"id\", id) // uses diagnostic_summary/diagnostic_detail\n   ```\n\n### Command-line usage\n\nThe [smarterr CLI](docs/cli.md) lets you check and inspect your configuration files.\n\n#### Commands\n\n- **Show the effective merged configuration:**\n\n  ```sh\n  smarterr config --base-dir /path/to/project --start-dir /path/to/project/internal/service\n  # or with short flags:\n  smarterr config -b /path/to/project -d /path/to/project/internal/service\n  ```\n\n  This prints the merged Config (after layering/merging) that would apply at the given directory.\n\n- **Check your configuration:**\n\n  ```sh\n  smarterr check --base-dir /path/to/project --start-dir /path/to/project/internal/service\n  # or with short flags:\n  smarterr check -b /path/to/project -d /path/to/project/internal/service\n  ```\n\n  This checks for parse errors, missing fields, schema issues, and other problems. smarterr returns a non-zero exit code if it finds errors.\n\n  **Flags:**\n  - `--quiet`, `-q`: Output errors (suppresses merged Config and warnings)\n  - `--silent`, `-S`: No output, just an exit code (non-zero if errors)\n  - `--debug`, `-D`: Enable debug output\n\n---\n\n## Example Configuration\n\nHere’s an example `smarterr.hcl` for a Terraform provider. For details, see the [full Config schema](docs/schema.md).\n\n```hcl\n#\ntemplate \"error_summary\" {\n  format = \"{{.happening}} {{.service}} {{.resource}} ({{.identifier}}): {{.error}}\"\n}\n\ntemplate \"diagnostic_summary\" {\n  format = \"{{.happening}} {{.service}} {{.resource}}: {{.diag.summary}}\"\n}\n\ntoken \"happening\" {\n  stack_matches = [\n    \"create\",\n  ]\n}\n\ntoken \"service\" {\n  parameter = \"service\"\n}\n\ntoken \"resource\" {\n  context = \"resource_name\"\n}\n\ntoken \"identifier\" {\n  arg = \"id\"\n}\n\ntoken \"error\" {\n  source = \"error\"\n  transforms = [\n    \"clean_aws_error\"\n  ]\n}\n\ntoken \"diag\" {\n  source = \"diagnostic\"\n  field_transforms = {\n    summary = [\"upper\"]\n    detail  = [\"lower\"]\n  }\n}\n\nstack_match \"create\" {\n  called_from = \"resource[a-zA-Z0-9]*Create\"\n  display     = \"creating\"\n}\n\nparameter \"service\" {\n  value = \"CloudWatch\"\n}\n\ntransform \"clean_aws_error\" {\n  step \"remove\" {\n    regex = \"RequestID: [a-z0-9-]+,\"\n  }\n  step \"remove\" {\n    value = \"InvalidParameterCombination: No\"\n  }\n  step \"remove\" {\n    value = \"https response error StatusCode: 400\"\n  }\n  step \"strip_suffix\" {\n    value = \",\"\n    recurse = true\n  }\n}\n```\n\n---\n\n## Diagnostic enrichment \u0026 structured tokens\n\nsmarterr supports Config-driven enrichment of both errors and framework-generated diagnostics (such as value conversion errors in Terraform Plugin Framework) using a structured diagnostic token.\n\n### Diagnostic token usage\n\n- Define a token with `source = \"diagnostic\"` to expose a structured token with fields (for example, `.diag.summary`, `.diag.detail`, `.diag.severity`).\n- Use `field_transforms` to apply transforms to individual fields of the diagnostic token.\n\nExample:\n\n```hcl\ntoken \"diag\" {\n  source = \"diagnostic\"\n  field_transforms = {\n    summary = [\"upper\"]\n    detail  = [\"lower\"]\n  }\n}\n```\n\nIn your template, access fields as `{{.diag.summary}}`, `{{.diag.detail}}`, etc.\n\nExample template:\n\n```hcl\ntemplate \"diagnostic_summary\" {\n  format = \"{{.happening}} {{.service}} {{.resource}}: {{.diag.summary}}\"\n}\n\ntemplate \"diagnostic_detail\" {\n  format = \"ID: {{.identifier}}\\nCause: {{.diag.detail}}\"\n}\n```\n\nThis enables context-rich diagnostics for both errors and framework-generated issues, all managed declaratively via Config.\n\n---\n\n## Learn more\n\n- [Full Config Schema](docs/schema.md)\n- [Layered configs \u0026 Merging](docs/layering.md)\n- [Diagnostics \u0026 Fallbacks](docs/diagnostics.md)\n- [API Reference](docs/api.md)\n- [FAQ](#faq)\n\n---\n\n## FAQ\n\n**Q: Do end users need to configure anything?**\nA: No. Developers of host applications embed the Config. End users get better errors.\n\n**Q: Can you update error messages without code changes?**\nA: Yes! Just update your Config and re-embed.\n\n**Q: What about missing or broken Config?**\nA: smarterr falls back to the original error, never panics. Use [`smarterr check`](#commands) and enable [debug mode](docs/schema.md#smarterr-optional) to find issues.\n\nFor more, see the [Diagnostics \u0026 Fallbacks](docs/diagnostics.md) doc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyakdriver%2Fsmarterr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyakdriver%2Fsmarterr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyakdriver%2Fsmarterr/lists"}