{"id":19865757,"url":"https://github.com/Antonboom/errname","last_synced_at":"2025-05-02T05:31:58.683Z","repository":{"id":38317787,"uuid":"388107703","full_name":"Antonboom/errname","owner":"Antonboom","description":"The Golang linter that checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error` or `Errors`.","archived":false,"fork":false,"pushed_at":"2025-05-01T04:51:49.000Z","size":135,"stargazers_count":25,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-01T14:49:14.117Z","etag":null,"topics":["go","golang","linter","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Antonboom.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":"2021-07-21T12:21:45.000Z","updated_at":"2025-03-13T10:35:47.000Z","dependencies_parsed_at":"2023-12-01T07:23:19.582Z","dependency_job_id":"37777c5e-7e11-449a-8c57-b8f30fef3174","html_url":"https://github.com/Antonboom/errname","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antonboom%2Ferrname","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antonboom%2Ferrname/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antonboom%2Ferrname/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Antonboom%2Ferrname/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Antonboom","download_url":"https://codeload.github.com/Antonboom/errname/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251992985,"owners_count":21677022,"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":["go","golang","linter","static-analysis"],"created_at":"2024-11-12T15:24:05.880Z","updated_at":"2025-05-02T05:31:53.669Z","avatar_url":"https://github.com/Antonboom.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# errname\n\n![Latest release](https://img.shields.io/github/v/release/Antonboom/errname)\n[![CI](https://github.com/Antonboom/errname/actions/workflows/ci.yml/badge.svg)](https://github.com/Antonboom/errname/actions/workflows/ci.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/Antonboom/errname)](https://goreportcard.com/report/github.com/Antonboom/errname)\n[![Coverage](https://coveralls.io/repos/github/Antonboom/errname/badge.svg?branch=master)](https://coveralls.io/github/Antonboom/errname?branch=master)\n[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)\n\nChecks that sentinel errors are prefixed with the `Err` and error types\nare suffixed with the `Error` or `Errors`.\n\n## Installation \u0026 usage\n\n```\n$ go install github.com/Antonboom/errname@latest\n$ errname ./...\n```\n\n## Motivation\n\n[The convention](https://go.dev/wiki/Errors#naming) states that\n\u003e Error types end in \"Error\" and error variables start with \"Err\" or \"err\".\n\nThis can be found in the standard Go library:\n\n```go\ntype AddrError struct{ /* ... */ }\ntype DecodeError struct{ /*...*/ }\ntype NoMatchingVersionError struct{ /*...*/ }\ntype nothingWrittenError struct{ /*...*/ }\ntype pasteIndicatorError struct{ /*...*/ }\ntype wrapError struct{ /*...*/ }\n\nvar ErrFinalToken = errors.New(\"final token\")\nvar ErrRange = errors.New(\"value out of range\")\nvar ErrUnsupportedAlgorithm = errors.New(\"x509: cannot verify signature: algorithm unimplemented\")\nvar errMissing = errors.New(\"cannot find package\")\nvar errNUL = errors.New(\"unexpected NUL in input\")\nvar errTagValueSpace = errors.New(\"suspicious space in struct tag value\")\n```\n\nAlso, this can be found in some articles about errors in Go, for\nexample, [here](https://travix.io/errors-derived-from-constants-in-go-fda6748b4072):\n\u003e At first sight you’d think the naming is a bit weird, but that is because of conventions: types are suffixed with\n\u003e “Error”, while constants are prefixed with “Err”. So we’re just following the conventions here.\n\nThis is a good rule to improve the consistency of your code. **More uniformity, what could be better?**\n\n### What if I think it's bullshit?\n\nJust don't enable the linter.\n\n### Why not [revive/error-naming](https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming)?\n\nAt the time of writing this linter, I was unaware of **revive**. \u003cbr\u003e\n**errname** performs more complex and better checks anyway.\n\n## Examples\n\n```go\n// Bad.\ntype DecodeErr struct{} // the error type name `DecodeErr` should conform to the `xxxError` format\nfunc (d *DecodeErr) Error() string { /*...*/ }\n\n// Good.\ntype DecodeError struct{}\nfunc (d *DecodeError) Error() string { /*...*/ }\n```\n\n```go\n// Bad.\nvar InvalidURLErr = errors.New(\"invalid url\") // the sentinel error name `InvalidURLErr` should conform to the `ErrXxx` format \n\n// Good.\nvar ErrInvalidURL = errors.New(\"invalid url\") // or errInvalidURL\n```\n\nMore examples in [tests](https://github.com/Antonboom/errname/blob/master/pkg/analyzer/facts_test.go).\n\n## Assumptions\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- Only package level variables (and constants) are checked.\n- Initialisms are ignored. As a result, all identifiers in a single case are ignored:\n\n```go\nvar EOF = errors.New(\"end of file\")\nvar eof = errors.New(\"end of file\")\nvar W = errors.New(\"single letter error\")   // on the developer's conscience\nvar ovflw = errors.New(\"value is overflow\") // on the developer's conscience\n```\n\n- The naming of error constructors is not checked. But I recommend keeping it consistent:\n\n```go\ntype DecodeError struct{}\nfunc (d *DecodeError) Error() string { /*...*/ }\n\n// Bad.\nfunc NewErrDecode() error {\n    return \u0026DecodeError{}\n}\n\n// Good.\nfunc NewDecodeError() error {\n    return \u0026DecodeError{}\n}\n```\n\n- Linter only checks the correctness of the suffix and prefix and their **uniqueness**. The logical meaning of the\n  identifier remains on the developer's conscience:\n\n```go\n// Bad.\nvar ErrExecErr = errors.New(\"exec query error\")\n\n// Good.\nvar ErrExecQuery = errors.New(\"exec query error\")\nvar ErrGdfjnskjdfskf = errors.New(\"strange error\") // on the developer's conscience\n```\n\n- For error types over array/slice the `Errors` suffix is also allowed:\n\n```go\n// Bad.\ntype ValidationErrs []string\nfunc (ve ValidationErrs) Error() string { /*...*/ }\n\n// Good.\ntype ValidationErrors []string\nfunc (ve ValidationErrors) Error() string { /*...*/ }\n```\n\n\u003c/details\u003e\n        \n## Large projects examples\n\n\u003cdetails\u003e\n  \u003csummary\u003eGolang source code\u003c/summary\u003e\n\n```go\n$ errname ./src/...\ngo/src/runtime/error.go:72:6: the error type name `errorString` should conform to the `xxxError` format\ngo/src/runtime/error.go:80:6: the error type name `errorAddressString` should conform to the `xxxError` format\ngo/src/runtime/panic.go:180:5: the sentinel error name `shiftError` should conform to the `errXxx` format\ngo/src/runtime/panic.go:187:5: the sentinel error name `divideError` should conform to the `errXxx` format\ngo/src/runtime/panic.go:194:5: the sentinel error name `overflowError` should conform to the `errXxx` format\ngo/src/runtime/panic.go:201:5: the sentinel error name `floatError` should conform to the `errXxx` format\ngo/src/runtime/panic.go:208:5: the sentinel error name `memoryError` should conform to the `errXxx` format\ngo/src/errors/errors.go:63:6: the error type name `errorString` should conform to the `xxxError` format\ngo/src/math/bits/bits_errors.go:12:5: the sentinel error name `overflowError` should conform to the `errXxx` format\ngo/src/math/bits/bits_errors.go:15:5: the sentinel error name `divideError` should conform to the `errXxx` format\ngo/src/syscall/syscall_unix.go:114:6: the error type name `Errno` should conform to the `XxxError` format\ngo/src/time/format.go:394:5: the sentinel error name `atoiError` should conform to the `errXxx` format\ngo/src/time/zoneinfo_read.go:110:5: the sentinel error name `badData` should conform to the `errXxx` format\ngo/src/io/fs/walk.go:15:5: the sentinel error name `SkipDir` should conform to the `ErrXxx` format\ngo/src/fmt/scan.go:465:5: the sentinel error name `complexError` should conform to the `errXxx` format\ngo/src/fmt/scan.go:466:5: the sentinel error name `boolError` should conform to the `errXxx` format\ngo/src/archive/tar/common.go:39:6: the error type name `headerError` should conform to the `xxxError` format\ngo/src/context/context.go:157:5: the sentinel error name `Canceled` should conform to the `ErrXxx` format\ngo/src/context/context.go:161:5: the sentinel error name `DeadlineExceeded` should conform to the `ErrXxx` format\ngo/src/math/big/float.go:77:6: the error type name `ErrNaN` should conform to the `XxxError` format\ngo/src/crypto/x509/internal/macos/security.go:39:6: the error type name `OSStatus` should conform to the `XxxError` format\ngo/src/net/cgo_unix.go:34:6: the error type name `addrinfoErrno` should conform to the `xxxError` format\ngo/src/crypto/x509/x509.go:875:6: the error type name `UnhandledCriticalExtension` should conform to the `XxxError` format\ngo/src/crypto/x509/pem_decrypt.go:110:5: the sentinel error name `IncorrectPasswordError` should conform to the `ErrXxx` format\ngo/src/crypto/x509/root.go:18:2: the sentinel error name `systemRootsErr` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:18:2: the sentinel error name `alertCloseNotify` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:19:2: the sentinel error name `alertUnexpectedMessage` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:20:2: the sentinel error name `alertBadRecordMAC` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:21:2: the sentinel error name `alertDecryptionFailed` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:22:2: the sentinel error name `alertRecordOverflow` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:23:2: the sentinel error name `alertDecompressionFailure` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:24:2: the sentinel error name `alertHandshakeFailure` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:25:2: the sentinel error name `alertBadCertificate` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:26:2: the sentinel error name `alertUnsupportedCertificate` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:27:2: the sentinel error name `alertCertificateRevoked` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:28:2: the sentinel error name `alertCertificateExpired` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:29:2: the sentinel error name `alertCertificateUnknown` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:30:2: the sentinel error name `alertIllegalParameter` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:31:2: the sentinel error name `alertUnknownCA` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:32:2: the sentinel error name `alertAccessDenied` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:33:2: the sentinel error name `alertDecodeError` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:34:2: the sentinel error name `alertDecryptError` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:35:2: the sentinel error name `alertExportRestriction` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:36:2: the sentinel error name `alertProtocolVersion` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:37:2: the sentinel error name `alertInsufficientSecurity` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:38:2: the sentinel error name `alertInternalError` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:39:2: the sentinel error name `alertInappropriateFallback` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:40:2: the sentinel error name `alertUserCanceled` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:41:2: the sentinel error name `alertNoRenegotiation` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:42:2: the sentinel error name `alertMissingExtension` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:43:2: the sentinel error name `alertUnsupportedExtension` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:44:2: the sentinel error name `alertCertificateUnobtainable` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:45:2: the sentinel error name `alertUnrecognizedName` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:46:2: the sentinel error name `alertBadCertificateStatusResponse` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:47:2: the sentinel error name `alertBadCertificateHashValue` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:48:2: the sentinel error name `alertUnknownPSKIdentity` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:49:2: the sentinel error name `alertCertificateRequired` should conform to the `errXxx` format\ngo/src/crypto/tls/alert.go:50:2: the sentinel error name `alertNoApplicationProtocol` should conform to the `errXxx` format\ngo/src/path/filepath/path.go:337:5: the sentinel error name `SkipDir` should conform to the `ErrXxx` format\ngo/src/net/http/h2_bundle.go:1016:5: the sentinel error name `http2errReadEmpty` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1212:2: the sentinel error name `http2errMixPseudoHeaderTypes` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1213:2: the sentinel error name `http2errPseudoAfterRegular` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1712:5: the sentinel error name `http2ErrFrameTooLarge` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1866:2: the sentinel error name `http2errStreamID` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1867:2: the sentinel error name `http2errDepStreamID` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1868:2: the sentinel error name `http2errPadLength` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:1869:2: the sentinel error name `http2errPadBytes` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3400:5: the sentinel error name `http2errTimeout` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3519:5: the sentinel error name `http2errClosedPipeWrite` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3629:2: the sentinel error name `http2errClientDisconnected` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3630:2: the sentinel error name `http2errClosedBody` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3631:2: the sentinel error name `http2errHandlerComplete` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:3632:2: the sentinel error name `http2errStreamClosed` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:4526:5: the sentinel error name `http2errPrefaceTimeout` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:4746:5: the sentinel error name `http2errHandlerPanicked` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:6287:2: the sentinel error name `http2ErrRecursivePush` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:6288:2: the sentinel error name `http2ErrPushLimitReached` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:6930:5: the sentinel error name `http2ErrNoCachedConn` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7016:2: the sentinel error name `http2errClientConnClosed` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7017:2: the sentinel error name `http2errClientConnUnusable` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7018:2: the sentinel error name `http2errClientConnGotGoAway` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7471:5: the sentinel error name `http2errRequestCanceled` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7803:2: the sentinel error name `http2errStopReqBodyWrite` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7806:2: the sentinel error name `http2errStopReqBodyWriteAndCancel` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:7808:2: the sentinel error name `http2errReqBodyTooLong` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:8667:5: the sentinel error name `http2errClosedResponseBody` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:9021:2: the sentinel error name `http2errResponseHeaderListSize` should conform to the `errXxx` format\ngo/src/net/http/h2_bundle.go:9022:2: the sentinel error name `http2errRequestHeaderListSize` should conform to the `errXxx` format\ngo/src/go/scanner/errors.go:37:6: the error type name `ErrorList` should conform to the `XxxError` format\ngo/src/html/template/template.go:34:5: the sentinel error name `escapeOK` should conform to the `errXxx` format\ngo/src/image/png/reader.go:128:5: the sentinel error name `chunkOrderError` should conform to the `errXxx` format\ngo/src/bufio/scan_test.go:308:5: the sentinel error name `testError` should conform to the `errXxx` format\ngo/src/crypto/tls/handshake_client_test.go:1993:5: the sentinel error name `brokenConnErr` should conform to the `errXxx` format\ngo/src/database/sql/sql_test.go:4281:5: the sentinel error name `pingError` should conform to the `errXxx` format\ngo/src/errors/wrap_test.go:216:6: the error type name `errorT` should conform to the `xxxError` format\ngo/src/errors/wrap_test.go:229:6: the error type name `errorUncomparable` should conform to the `xxxError` format\ngo/src/fmt/errors_test.go:75:6: the error type name `errString` should conform to the `xxxError` format\ngo/src/html/template/exec_test.go:233:5: the sentinel error name `myError` should conform to the `errXxx` format\ngo/src/html/template/exec_test.go:1313:5: the sentinel error name `alwaysError` should conform to the `errXxx` format\ngo/src/net/http/transport_test.go:6280:5: the sentinel error name `timeoutProtoErr` should conform to the `errXxx` format\ngo/src/text/template/exec_test.go:229:5: the sentinel error name `myError` should conform to the `errXxx` format\ngo/src/text/template/exec_test.go:1305:5: the sentinel error name `alwaysError` should conform to the `errXxx` format\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eTraefik\u003c/summary\u003e\n\n```go\n$ errname./...\n# no issues\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eTerraform\u003c/summary\u003e\n\n```go\n$ errname./...\nterraform/internal/getmodules/file_detector.go:59:6: the error type name `MaybeRelativePathErr` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:13:6: the error type name `ErrHostNoProviders` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:39:6: the error type name `ErrHostUnreachable` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:57:6: the error type name `ErrUnauthorized` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:80:6: the error type name `ErrProviderNotFound` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:104:6: the error type name `ErrRegistryProviderNotKnown` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:123:6: the error type name `ErrPlatformNotSupported` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:159:6: the error type name `ErrProtocolNotSupported` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:181:6: the error type name `ErrQueryFailed` should conform to the `XxxError` format\nterraform/internal/getproviders/errors.go:219:6: the error type name `ErrRequestCanceled` should conform to the `XxxError` format\nterraform/internal/registry/errors.go:10:6: the error type name `errModuleNotFound` should conform to the `xxxError` format\nterraform/internal/backend/remote-state/consul/client.go:36:5: the sentinel error name `lostLockErr` should conform to the `errXxx` format\nterraform/internal/command/cliconfig/credentials.go:408:6: the error type name `ErrUnwritableHostCredentials` should conform to the `XxxError` format\n```\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAntonboom%2Ferrname","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAntonboom%2Ferrname","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAntonboom%2Ferrname/lists"}