{"id":13740907,"url":"https://github.com/lpil/snag","last_synced_at":"2026-02-03T14:31:45.502Z","repository":{"id":136877038,"uuid":"350327779","full_name":"lpil/snag","owner":"lpil","description":"⛵ A boilerplate-free ad-hoc error type","archived":false,"fork":false,"pushed_at":"2025-11-02T11:04:45.000Z","size":34,"stargazers_count":73,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-02T13:05:53.349Z","etag":null,"topics":["error-handling","gleam"],"latest_commit_sha":null,"homepage":"","language":"Gleam","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lpil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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}},"created_at":"2021-03-22T12:02:58.000Z","updated_at":"2025-11-02T11:04:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"ec1dd9c0-89c5-40e6-a785-49855f193408","html_url":"https://github.com/lpil/snag","commit_stats":null,"previous_names":["gleam-experiments/snag"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/lpil/snag","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fsnag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fsnag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fsnag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fsnag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lpil","download_url":"https://codeload.github.com/lpil/snag/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fsnag/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29047565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T10:09:22.136Z","status":"ssl_error","status_checked_at":"2026-02-03T10:09:16.814Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["error-handling","gleam"],"created_at":"2024-08-03T04:00:53.462Z","updated_at":"2026-02-03T14:31:45.483Z","avatar_url":"https://github.com/lpil.png","language":"Gleam","funding_links":[],"categories":["Packages"],"sub_categories":["Error Handling"],"readme":"# Snag\n\nA Snag is a boilerplate-free ad-hoc error type.\n\nUse `Result(value, Snag)` (or the `snag.Result(value)` alias) in functions\nthat may fail.\n\nA low level message like \"Unexpected status 401\" or \"No such file or\ndirectory\" can be confusing or difficult to debug, so use the `snag.context`\nfunction to add extra contextual information.\n\n```gleam\nimport gleam/io\nimport gleam/result\nimport my_app.{User}\nimport snag.{type Result}\n\npub fn log_in(user_id: Int) -\u003e Result(User) {\n  use api_key \u003c- result.try(\n    my_app.read_file(\"api_key.txt\")\n    |\u003e snag.context(\"Could not load API key\")\n  )\n\n  use session_token \u003c- result.try(\n    user_id\n    |\u003e my_app.create_session(api_key)\n    |\u003e snag.context(\"Session creation failed\")\n  )\n\n  Ok(session_token)\n}\n\npub fn main() {\n  case log_in(42) {\n    Ok(session) -\u003e io.println(\"Logged in!\")\n    Error(snag) -\u003e {\n      io.print(snag.pretty_print(snag))\n      my_app.exit(1)\n    }\n  }\n}\n```\n\nIn this code when an error occurs within the `create_session` function an\nerror message like this is printed using the added contextual information:\n\n```text\nerror: Session creation failed\n\ncause:\n  0: Unable to exchange token with authentication service\n  1: Service authentication failed\n  2: Unexpected HTTP status 401\n```\n\n## When should I use Snag?\n\nSnag is useful in code where it must either pass or fail, and when it fails we\nwant good debugging information to print to the user. i.e. Command line\ntools, data processing pipelines, etc. Here Snag provides a convenient way to\ncreate errors with a reasonable amount of debugging information, without the\nboilerplate of a custom error type.\n\nIt is not suited to code where the application needs to make a decision about\nwhat to do in the event of an error, such as whether to give up or to try\nagain. i.e. Libraries, web application backends, API clients, etc. In these\nsituations it is recommended to create a custom type for your errors as it\ncan be pattern matched on and have any additional detail added as fields.\n\n## Installation\n\nAdd `snag` to your Gleam project\n\n```\ngleam add snag\n```\n\n## Prior art\n\nThis library is inspired by the following projects:\n\n- Rust's [`anyhow`](https://github.com/dtolnay/anyhow) and\n  [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html)\n- Go's [`error`](https://golang.org/pkg/errors/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpil%2Fsnag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flpil%2Fsnag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpil%2Fsnag/lists"}