Go linter that checks types that are json encoded - reports unsupported types and unnecessary error checks

errchkjson

Test Status Go Report Card License

Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omited.

Consider this http.Handler:

func JSONHelloWorld(w http.ResponseWriter, r *http.Request) {
	response := struct {
		Message string
		Code    int
	}{
		Message: "Hello World",
		Code:    200,
	}

	body, err := json.Marshal(response)
	if err != nil {
		panic(err) // unreachable, because json encoding of a struct with just a string and an int will never return an error.
	}

	w.Write(body)
}

Because the panic is not possible to happen, one might refactor the code like this:

func JSONHelloWorld(w http.ResponseWriter, r *http.Request) {
	response := struct {
		Message string
		Code    int
	}{
		Message: "Hello World",
		Code:    200,
	}

	body, _ := json.Marshal(response)

	w.Write(body)
}

This is ok, as long as the struct is not altered in such a way, that could potentially lead to json.Marshal returning an error.

errchkjson allows you to lint your code such that the above error returned from json.Marshal can be omitted while still staying save, because as soon as an unsafe type is added to the response type, the linter will warn you.

Installation

Download errchkjson from the releases or get the latest version from source with:

go get github.com/breml/errchkjson/cmd/errchkjson

Usage

Shell

Check everything:

errchkjson ./...

errchkjson also recognizes the following command-line options:

The -omit-safe flag disables checking for safe returns of errors from json.Marshal

Types

Safe

The following types are safe to use with json encoding functions, that is, the encoding to JSON can not fail:

Safe basic types:

  • bool
  • int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr
  • string
  • Pointer type of the above listed basic types

Composed types (struct, map, slice, array) are safe, if the type of the value is safe. For structs, only exported fields are relevant. For maps, the key needs to be either an integer type or a string.

Unsafe

The following types are unsafe to use with json encoding functions, that is, the encoding to JSON can fail (return an error):

Unsafe basic types:

  • float32, float64
  • interface{}
  • Pointer type of the above listed basic types

Any composed types (struct, map, slice, array) containing an unsafe basic type.

If a type implements the json.Marshaler or encoding.TextMarshaler interface (e.g. json.Number).

Forbidden

Forbidden basic types:

  • complex64, complex128
  • chan
  • func
  • unsafe.Pointer

Any composed types (struct, map, slice, array) containing a forbidden basic type. Any map using a key with a forbidden type (bool, float32, float64, struct).

Bugs found during development

During the development of errcheckjson, the following issues in package encoding/json of the Go standard library have been found and PR have been merged:

Owner
Lucas Bremgartner
More than 10 years experience in software engineering. Working with different programming languages and in multiple fields of IT for more than 20 years.
Lucas Bremgartner
Comments
  • Stack overflow while running linter

    Stack overflow while running linter

    I have been using golangci-lint with most linters enabled, and in the latest version your linter has been added as a default.

    However this crashes the linter with a stack overflow. Can you see what is happening from this stacktrace?

    paul@paul-ThinkPad  ~/project  golangci-lint version
    golangci-lint has version 1.44.0 built from 617470fa on 2022-01-25T11:31:17Z
    
    paul@paul-ThinkPad  ~/project  golangci-lint run 
    runtime: goroutine stack exceeds 1000000000-byte limit
    runtime: sp=0xc03500e4e8 stack=[0xc03500e000, 0xc05500e000]
    fatal error: stack overflow
    
    runtime stack:
    runtime.throw({0x10038d3, 0x18155e0})
    	runtime/panic.go:1198 +0x71
    runtime.newstack()
    	runtime/stack.go:1088 +0x5ac
    runtime.morestack()
    	runtime/asm_amd64.s:461 +0x8b
    
    goroutine 4392 [running]:
    go/types.(*Named).under(0xc0046f9a00)
    	go/types/decl.go:579 +0x679 fp=0xc03500e4f8 sp=0xc03500e4f0 pc=0x7db279
    go/types.under({0x11ac430, 0xc0046f9a00})
    	go/types/type.go:909 +0x2f fp=0xc03500e518 sp=0xc03500e4f8 pc=0x80e2ef
    go/types.asTypeParam({0x11ac430, 0xc0046f9a00})
    	go/types/type.go:987 +0x25 fp=0xc03500e538 sp=0xc03500e518 pc=0x80e785
    go/types.optype({0x11ac430, 0xc0046f9a00})
    	go/types/type.go:783 +0x2c fp=0xc03500e578 sp=0xc03500e538 pc=0x80d82c
    go/types.asInterface(...)
    	go/types/type.go:963
    go/types.IsInterface({0x11ac430, 0xc0046f9a00})
    	go/types/predicates.go:86 +0x25 fp=0xc03500e598 sp=0xc03500e578 pc=0x7f7aa5
    go/types.(*Checker).rawLookupFieldOrMethod(0x11ac430, {0x11ac4a8, 0xc00418ad70}, 0x0, 0x1, {0xfd2a03, 0xb})
    	go/types/lookup.go:89 +0xea fp=0xc03500e858 sp=0xc03500e598 pc=0x7f0c2a
    go/types.(*Checker).missingMethod(0x0, {0x11ac430, 0xc0046f9a00}, 0xc00363fd80, 0x1)
    	go/types/lookup.go:361 +0x4f4 fp=0xc03500e928 sp=0xc03500e858 pc=0x7f27d4
    go/types.MissingMethod(...)
    	go/types/lookup.go:295
    go/types.Implements({0x11ac430, 0xc0046f9a00}, 0xc0046f9a00)
    	go/types/api.go:320 +0x33 fp=0xc03500e960 sp=0xc03500e928 pc=0x7c8d93
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffdb)
    	github.com/breml/[email protected]/errchkjson.go:153 +0x55 fp=0xc03500e9e0 sp=0xc03500e960 pc=0x9d8995
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffda)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ea60 sp=0xc03500e9e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffd9)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500eae0 sp=0xc03500ea60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffd8)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500eb60 sp=0xc03500eae0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffd7)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500ebe0 sp=0xc03500eb60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffd6)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ec60 sp=0xc03500ebe0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffd5)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500ece0 sp=0xc03500ec60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffd4)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ed60 sp=0xc03500ece0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffd3)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500ede0 sp=0xc03500ed60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffd2)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ee60 sp=0xc03500ede0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffd1)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500eee0 sp=0xc03500ee60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffd0)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ef60 sp=0xc03500eee0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffcf)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500efe0 sp=0xc03500ef60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffce)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f060 sp=0xc03500efe0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffcd)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f0e0 sp=0xc03500f060 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffcc)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f160 sp=0xc03500f0e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffcb)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f1e0 sp=0xc03500f160 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffca)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f260 sp=0xc03500f1e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffc9)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f2e0 sp=0xc03500f260 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffc8)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f360 sp=0xc03500f2e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffc7)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f3e0 sp=0xc03500f360 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffc6)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f460 sp=0xc03500f3e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffc5)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f4e0 sp=0xc03500f460 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffc4)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f560 sp=0xc03500f4e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffc3)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f5e0 sp=0xc03500f560 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffc2)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f660 sp=0xc03500f5e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffc1)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f6e0 sp=0xc03500f660 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffc0)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f760 sp=0xc03500f6e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffbf)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f7e0 sp=0xc03500f760 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffbe)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f860 sp=0xc03500f7e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffbd)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f8e0 sp=0xc03500f860 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffbc)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500f960 sp=0xc03500f8e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffbb)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500f9e0 sp=0xc03500f960 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffba)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500fa60 sp=0xc03500f9e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffb9)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500fae0 sp=0xc03500fa60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffb8)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500fb60 sp=0xc03500fae0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffb7)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500fbe0 sp=0xc03500fb60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffb6)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500fc60 sp=0xc03500fbe0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffb5)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500fce0 sp=0xc03500fc60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffb4)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500fd60 sp=0xc03500fce0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffb3)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500fde0 sp=0xc03500fd60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffb2)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500fe60 sp=0xc03500fde0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffb1)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500fee0 sp=0xc03500fe60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffb0)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc03500ff60 sp=0xc03500fee0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffaf)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc03500ffe0 sp=0xc03500ff60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffae)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010060 sp=0xc03500ffe0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffad)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350100e0 sp=0xc035010060 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffac)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010160 sp=0xc0350100e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffab)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350101e0 sp=0xc035010160 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffaa)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010260 sp=0xc0350101e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffa9)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350102e0 sp=0xc035010260 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffa8)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010360 sp=0xc0350102e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffa7)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350103e0 sp=0xc035010360 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffa6)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010460 sp=0xc0350103e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffa5)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350104e0 sp=0xc035010460 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffa4)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010560 sp=0xc0350104e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffa3)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350105e0 sp=0xc035010560 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffa2)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010660 sp=0xc0350105e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fffa1)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350106e0 sp=0xc035010660 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fffa0)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010760 sp=0xc0350106e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff9f)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350107e0 sp=0xc035010760 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff9e)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010860 sp=0xc0350107e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff9d)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350108e0 sp=0xc035010860 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff9c)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010960 sp=0xc0350108e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff9b)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350109e0 sp=0xc035010960 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff9a)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010a60 sp=0xc0350109e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff99)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010ae0 sp=0xc035010a60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff98)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010b60 sp=0xc035010ae0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff97)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010be0 sp=0xc035010b60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff96)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010c60 sp=0xc035010be0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff95)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010ce0 sp=0xc035010c60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff94)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010d60 sp=0xc035010ce0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff93)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010de0 sp=0xc035010d60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff92)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010e60 sp=0xc035010de0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff91)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010ee0 sp=0xc035010e60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff90)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035010f60 sp=0xc035010ee0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff8f)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc035010fe0 sp=0xc035010f60 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff8e)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011060 sp=0xc035010fe0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff8d)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350110e0 sp=0xc035011060 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff8c)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011160 sp=0xc0350110e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff8b)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350111e0 sp=0xc035011160 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff8a)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011260 sp=0xc0350111e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff89)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350112e0 sp=0xc035011260 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff88)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011360 sp=0xc0350112e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff87)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350113e0 sp=0xc035011360 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff86)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011460 sp=0xc0350113e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff85)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350114e0 sp=0xc035011460 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff84)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011560 sp=0xc0350114e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff83)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350115e0 sp=0xc035011560 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff82)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011660 sp=0xc0350115e0 pc=0x9d8e77
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac430, 0xc0046f9a00}, 0x3fff81)
    	github.com/breml/[email protected]/errchkjson.go:205 +0x6ee fp=0xc0350116e0 sp=0xc035011660 pc=0x9d902e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc000afea30, {0x11ac4a8, 0xc0068c7df0}, 0x3fff80)
    	github.com/breml/[email protected]/errchkjson.go:217 +0x537 fp=0xc035011760 sp=0xc0350116e0 pc=0x9d8e77
    created by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:75 +0x1fd
    
    goroutine 1 [semacquire]:
    sync.runtime_Semacquire(0xc0006d72a0)
    	runtime/sema.go:56 +0x25
    sync.(*WaitGroup).Wait(0xc001635130)
    	sync/waitgroup.go:130 +0x71
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*runner).analyze(0xc0012ff590, {0xc001474dc0, 0x40, 0xc0011a3470}, {0xc001010e00, 0xb1, 0xe0})
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go:279 +0x5ec
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*runner).run(0xc0012ff590, {0xc001010e00, 0xb1, 0xe0}, {0xc001474dc0, 0xb1, 0x8})
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go:86 +0x1a5
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.runAnalyzers({0x11c45b8, 0xc000c86080}, 0xc0005355e0)
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runners.go:52 +0x565
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.MetaLinter.Run({{0xc0002a5600, 0xc000c22ff0, 0x140}, 0xc000399bc0}, {0x10, 0x100000000000010}, 0x7f961de56030)
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/metalinter.go:31 +0x165
    github.com/golangci/golangci-lint/pkg/lint.(*Runner).runLinterSafe(0x0, {0x11b7788, 0xc000c52ae0}, 0x203000, 0xc0002b9d80)
    	github.com/golangci/golangci-lint/pkg/lint/runner.go:120 +0xcc
    github.com/golangci/golangci-lint/pkg/lint.Runner.Run.func1()
    	github.com/golangci/golangci-lint/pkg/lint/runner.go:204 +0x65
    github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000c46d70, {0x1018d71, 0x15}, 0xc0002679f8)
    	github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x4a
    github.com/golangci/golangci-lint/pkg/lint.Runner.Run({{0xc000cc0640, 0x14, 0x14}, {0x11c8c00, 0xc00090f110}}, {0x11b7788, 0xc000c52ae0}, {0xc0011a3510, 0x1, 0x1}, ...)
    	github.com/golangci/golangci-lint/pkg/lint/runner.go:203 +0x2c6
    github.com/golangci/golangci-lint/pkg/commands.(*Executor).runAnalysis(0xc000242c00, {0x11b7788, 0xc000c52ae0}, {0x1a0c1c8, 0x19d12e0, 0x11b7788})
    	github.com/golangci/golangci-lint/pkg/commands/run.go:359 +0x513
    github.com/golangci/golangci-lint/pkg/commands.(*Executor).runAndPrint(0xc000242c00, {0x11b7788, 0xc000c52ae0}, {0x1a0c1c8, 0x0, 0x0})
    	github.com/golangci/golangci-lint/pkg/commands/run.go:400 +0x1e5
    github.com/golangci/golangci-lint/pkg/commands.(*Executor).executeRun(0xc000242c00, 0xc000267d88, {0x1a0c1c8, 0x0, 0x0})
    	github.com/golangci/golangci-lint/pkg/commands/run.go:513 +0x248
    github.com/spf13/cobra.(*Command).execute(0xc000511180, {0x1a0c1c8, 0x0, 0x0})
    	github.com/spf13/[email protected]/command.go:860 +0x5f8
    github.com/spf13/cobra.(*Command).ExecuteC(0xc000510f00)
    	github.com/spf13/[email protected]/command.go:974 +0x3bc
    github.com/spf13/cobra.(*Command).Execute(...)
    	github.com/spf13/[email protected]/command.go:902
    github.com/golangci/golangci-lint/pkg/commands.(*Executor).Execute(...)
    	github.com/golangci/golangci-lint/pkg/commands/executor.go:147
    main.main()
    	github.com/golangci/golangci-lint/cmd/golangci-lint/main.go:21 +0x4f
    
    goroutine 538 [semacquire]:
    sync.runtime_Semacquire(0x0)
    	runtime/sema.go:56 +0x25
    sync.(*WaitGroup).Wait(0x203000)
    	sync/waitgroup.go:130 +0x71
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze(0xc000bb9620, 0x2, 0xc001ca2000)
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:83 +0x2d7
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyzeRecursive.func1()
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:48 +0x1ae
    sync.(*Once).doSlow(0x11ace58, 0xc0000637d0)
    	sync/once.go:68 +0xd2
    sync.(*Once).Do(...)
    	sync/once.go:59
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyzeRecursive(0xc001679001, 0x43e6e5, 0xc000245080)
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:37 +0x52
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*runner).analyze.func2(0x0)
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go:274 +0x2e
    created by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*runner).analyze
    	github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go:273 +0x5da
    

    Let me know if you need more information!

  • Skipping error checks for `json.Encoder.Encode` or `json.MarshalIndent` is not safe

    Skipping error checks for `json.Encoder.Encode` or `json.MarshalIndent` is not safe

    $ cat t.go
    package main
    
    import (
    	"encoding/json"
    	"os"
    )
    
    type Foo struct {
    	X string
    }
    
    func main() {
    	err := json.NewEncoder(os.Stdout).Encode(Foo{"bar"})
    	if err != nil {
    		panic("meh")
    	}
    }
    $ ./errchkjson t.go
    t.go:13:9: Error return value of `(*encoding/json.Encoder).Encode` is checked but passed argument is safe
    $ ./errchkjson -V
    errchkjson version 0.2.3
    commit: 3aae21891fb6867e0ae247403f8eb67c0573c5d5
    built at: 2022-02-08T16:17:38Z
    module version: v0.2.3, checksum: h1:97eGTmR/w0paL2SwfRPI1jaAZHaH/fXnxWTw2eEIqE0=
    goos: linux
    goarch: amd64
    

    json.Encoder.Encode can return an error due to a number of reasons unrelated to the argument's general JSON marshal safety:

    • https://cs.opensource.google/go/go/+/refs/tags/go1.17.6:src/encoding/json/stream.go;l=202
    • https://cs.opensource.google/go/go/+/refs/tags/go1.17.6:src/encoding/json/stream.go;l=225
    • https://cs.opensource.google/go/go/+/refs/tags/go1.17.6:src/encoding/json/stream.go;l=231

    The same applies to json.MarshalIndent:

    • https://cs.opensource.google/go/go/+/refs/tags/go1.17.6:src/encoding/json/encode.go;l=181

    I think errchkjson should not encourage skipping error checks for these functions at all.

    (Haven't thought through if there are other messages in errchkjson that should be adjusted due to these considerations, but I suspect there might be some.)

  • tests: add case for looping structure (stack overflow)

    tests: add case for looping structure (stack overflow)

    this currently fails with the following error.

    unfortunately I don't have time to investigate a fix, but hope this helps with reproducing it.

    -*- mode: compilation; default-directory: "~/dev/other/errchkjson/" -*-
    Compilation started at Thu Jan 27 14:18:22
    
    go test -run='TestLoop$' 
    runtime: goroutine stack exceeds 1000000000-byte limit
    runtime: sp=0xc02d0004c8 stack=[0xc02d000000, 0xc04d000000]
    fatal error: stack overflow
    
    runtime stack:
    runtime.throw({0x6985f4, 0x84e620})
    	/usr/lib/go/src/runtime/panic.go:1198 +0x71
    runtime.newstack()
    	/usr/lib/go/src/runtime/stack.go:1088 +0x5ac
    runtime.morestack()
    	/usr/lib/go/src/runtime/asm_amd64.s:461 +0x8b
    
    goroutine 596 [running]:
    go/types.(*Named).under(0xc00875b280)
    	/usr/lib/go/src/go/types/decl.go:579 +0x679 fp=0xc02d0004d8 sp=0xc02d0004d0 pc=0x56d359
    go/types.under({0x6eee58, 0xc00875b280})
    	/usr/lib/go/src/go/types/type.go:909 +0x2f fp=0xc02d0004f8 sp=0xc02d0004d8 pc=0x59d5ef
    go/types.asTypeParam({0x6eee58, 0xc00875b280})
    	/usr/lib/go/src/go/types/type.go:987 +0x25 fp=0xc02d000518 sp=0xc02d0004f8 pc=0x59da85
    go/types.optype({0x6eee58, 0xc00875b280})
    	/usr/lib/go/src/go/types/type.go:783 +0x2c fp=0xc02d000558 sp=0xc02d000518 pc=0x59cb2c
    go/types.asInterface(...)
    	/usr/lib/go/src/go/types/type.go:963
    go/types.IsInterface({0x6eee58, 0xc00875b280})
    	/usr/lib/go/src/go/types/predicates.go:86 +0x25 fp=0xc02d000578 sp=0xc02d000558 pc=0x587765
    go/types.(*Checker).rawLookupFieldOrMethod(0x6eee58, {0x6eee80, 0xc00c517f90}, 0x0, 0x1, {0x697366, 0xb})
    	/usr/lib/go/src/go/types/lookup.go:89 +0xea fp=0xc02d000838 sp=0xc02d000578 pc=0x58258a
    go/types.(*Checker).missingMethod(0x0, {0x6eee58, 0xc00875b280}, 0xc004a58200, 0x1)
    	/usr/lib/go/src/go/types/lookup.go:361 +0x4f4 fp=0xc02d000908 sp=0xc02d000838 pc=0x584134
    go/types.MissingMethod(...)
    	/usr/lib/go/src/go/types/lookup.go:295
    go/types.Implements({0x6eee58, 0xc00875b280}, 0xc0087f00a6)
    	/usr/lib/go/src/go/types/api.go:320 +0x33 fp=0xc02d000940 sp=0xc02d000908 pc=0x55af53
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffd6)
    	/home/mark/dev/other/errchkjson/errchkjson.go:153 +0x55 fp=0xc02d0009c0 sp=0xc02d000940 pc=0x5b23d5
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffd5)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000a40 sp=0xc02d0009c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffd4)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000ac0 sp=0xc02d000a40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffd3)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000b40 sp=0xc02d000ac0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffd2)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000bc0 sp=0xc02d000b40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffd1)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000c40 sp=0xc02d000bc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffd0)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000cc0 sp=0xc02d000c40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffcf)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000d40 sp=0xc02d000cc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffce)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000dc0 sp=0xc02d000d40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffcd)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000e40 sp=0xc02d000dc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffcc)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000ec0 sp=0xc02d000e40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffcb)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d000f40 sp=0xc02d000ec0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffca)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d000fc0 sp=0xc02d000f40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffc9)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001040 sp=0xc02d000fc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffc8)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0010c0 sp=0xc02d001040 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffc7)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001140 sp=0xc02d0010c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffc6)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0011c0 sp=0xc02d001140 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffc5)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001240 sp=0xc02d0011c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffc4)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0012c0 sp=0xc02d001240 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffc3)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001340 sp=0xc02d0012c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffc2)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0013c0 sp=0xc02d001340 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffc1)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001440 sp=0xc02d0013c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffc0)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0014c0 sp=0xc02d001440 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffbf)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001540 sp=0xc02d0014c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffbe)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0015c0 sp=0xc02d001540 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffbd)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001640 sp=0xc02d0015c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffbc)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0016c0 sp=0xc02d001640 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffbb)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001740 sp=0xc02d0016c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffba)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0017c0 sp=0xc02d001740 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffb9)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001840 sp=0xc02d0017c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffb8)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0018c0 sp=0xc02d001840 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffb7)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001940 sp=0xc02d0018c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffb6)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0019c0 sp=0xc02d001940 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffb5)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001a40 sp=0xc02d0019c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffb4)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001ac0 sp=0xc02d001a40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffb3)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001b40 sp=0xc02d001ac0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffb2)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001bc0 sp=0xc02d001b40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffb1)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001c40 sp=0xc02d001bc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffb0)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001cc0 sp=0xc02d001c40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffaf)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001d40 sp=0xc02d001cc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffae)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001dc0 sp=0xc02d001d40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffad)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001e40 sp=0xc02d001dc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffac)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001ec0 sp=0xc02d001e40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffab)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d001f40 sp=0xc02d001ec0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffaa)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d001fc0 sp=0xc02d001f40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffa9)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002040 sp=0xc02d001fc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffa8)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0020c0 sp=0xc02d002040 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffa7)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002140 sp=0xc02d0020c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffa6)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0021c0 sp=0xc02d002140 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffa5)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002240 sp=0xc02d0021c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffa4)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0022c0 sp=0xc02d002240 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffa3)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002340 sp=0xc02d0022c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffa2)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0023c0 sp=0xc02d002340 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fffa1)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002440 sp=0xc02d0023c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fffa0)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0024c0 sp=0xc02d002440 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff9f)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002540 sp=0xc02d0024c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff9e)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0025c0 sp=0xc02d002540 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff9d)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002640 sp=0xc02d0025c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff9c)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0026c0 sp=0xc02d002640 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff9b)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002740 sp=0xc02d0026c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff9a)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0027c0 sp=0xc02d002740 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff99)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002840 sp=0xc02d0027c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff98)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0028c0 sp=0xc02d002840 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff97)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002940 sp=0xc02d0028c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff96)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0029c0 sp=0xc02d002940 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff95)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002a40 sp=0xc02d0029c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff94)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002ac0 sp=0xc02d002a40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff93)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002b40 sp=0xc02d002ac0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff92)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002bc0 sp=0xc02d002b40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff91)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002c40 sp=0xc02d002bc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff90)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002cc0 sp=0xc02d002c40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff8f)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002d40 sp=0xc02d002cc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff8e)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002dc0 sp=0xc02d002d40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff8d)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002e40 sp=0xc02d002dc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff8c)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002ec0 sp=0xc02d002e40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff8b)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d002f40 sp=0xc02d002ec0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff8a)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d002fc0 sp=0xc02d002f40 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff89)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003040 sp=0xc02d002fc0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff88)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0030c0 sp=0xc02d003040 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff87)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003140 sp=0xc02d0030c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff86)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0031c0 sp=0xc02d003140 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff85)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003240 sp=0xc02d0031c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff84)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0032c0 sp=0xc02d003240 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff83)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003340 sp=0xc02d0032c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff82)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0033c0 sp=0xc02d003340 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff81)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003440 sp=0xc02d0033c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff80)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0034c0 sp=0xc02d003440 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff7f)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003540 sp=0xc02d0034c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff7e)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0035c0 sp=0xc02d003540 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff7d)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003640 sp=0xc02d0035c0 pc=0x5b2a6e
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b280}, 0x3fff7c)
    	/home/mark/dev/other/errchkjson/errchkjson.go:186 +0x3fb fp=0xc02d0036c0 sp=0xc02d003640 pc=0x5b277b
    github.com/breml/errchkjson.(*errchkjson).jsonSafe(0xc0000bc9d0, {0x6eee58, 0xc00875b200}, 0x3fff7b)
    	/home/mark/dev/other/errchkjson/errchkjson.go:205 +0x6ee fp=0xc02d003740 sp=0xc02d0036c0 pc=0x5b2a6e
    created by golang.org/x/tools/go/analysis/internal/checker.execAll
    	/home/mark/go/pkg/mod/golang.org/x/[email protected]/go/analysis/internal/checker/checker.go:573 +0x168
    
    goroutine 1 [chan receive]:
    testing.(*T).Run(0xc0001064e0, {0x696433, 0x469193}, 0x6a93b8)
    	/usr/lib/go/src/testing/testing.go:1307 +0x375
    testing.runTests.func1(0xc0001064e0)
    	/usr/lib/go/src/testing/testing.go:1598 +0x6e
    testing.tRunner(0xc0001064e0, 0xc000117d18)
    	/usr/lib/go/src/testing/testing.go:1259 +0x102
    testing.runTests(0xc0000d6480, {0x862020, 0x4, 0x4}, {0x48058d, 0x69863a, 0x867cc0})
    	/usr/lib/go/src/testing/testing.go:1596 +0x43f
    testing.(*M).Run(0xc0000d6480)
    	/usr/lib/go/src/testing/testing.go:1504 +0x51d
    main.main()
    	_testmain.go:51 +0x14b
    
    goroutine 18 [semacquire]:
    sync.runtime_Semacquire(0x0)
    	/usr/lib/go/src/runtime/sema.go:56 +0x25
    sync.(*WaitGroup).Wait(0x0)
    	/usr/lib/go/src/sync/waitgroup.go:130 +0x71
    golang.org/x/tools/go/analysis/internal/checker.execAll({0xc008bb4740, 0x1, 0xc000312076})
    	/home/mark/go/pkg/mod/golang.org/x/[email protected]/go/analysis/internal/checker/checker.go:576 +0x172
    golang.org/x/tools/go/analysis/internal/checker.analyze({0xc008bb4738, 0x1, 0x0}, {0xc000093d68, 0x1, 0xc008bb4738})
    	/home/mark/go/pkg/mod/golang.org/x/[email protected]/go/analysis/internal/checker/checker.go:262 +0x1bf
    golang.org/x/tools/go/analysis/internal/checker.TestAnalyzer(0xc0000a6090, {0xc008bb4738, 0xc00009f7d0, 0x1})
    	/home/mark/go/pkg/mod/golang.org/x/[email protected]/go/analysis/internal/checker/checker.go:179 +0x65
    golang.org/x/tools/go/analysis/analysistest.Run({0x6ea660, 0xc000106680}, {0xc0000a6090, 0x28}, 0x0, {0xc00009f7d0, 0x1, 0x1})
    	/home/mark/go/pkg/mod/golang.org/x/[email protected]/go/analysis/analysistest/analysistest.go:291 +0xd2
    github.com/breml/errchkjson_test.TestLoop(0x0)
    	/home/mark/dev/other/errchkjson/errchkjson_test.go:47 +0x8a
    testing.tRunner(0xc000106680, 0x6a93b8)
    	/usr/lib/go/src/testing/testing.go:1259 +0x102
    created by testing.(*T).Run
    	/usr/lib/go/src/testing/testing.go:1306 +0x35a
    exit status 2
    FAIL	github.com/breml/errchkjson	48.242s
    
    Compilation exited abnormally with code 1 at Thu Jan 27 14:19:11
    
  • False positive for multiple return values

    False positive for multiple return values

    Given the following code:

    package main
    
    type T struct {
        s string
    }
    
    func (t T) MarshalJSON() ([]byte, error) {
        return json.Marshal(t.s)
    }
    

    errchkjson reports the error:

    t.go:8:5: Error return value of `encoding/json.Marshal` is not checked (errchkjson)
            return json.Marshal(t.s)
    

    which is a false positive, as it is the caller's responsibility to check the return value from T.MarshalJSON.

  • `json.Marshaler` implementors not treated unsafe?

    `json.Marshaler` implementors not treated unsafe?

    From README.md, things treated as unsafe:

    If a type implements the json.Marshaler or encoding.TextMarshaler interface (e.g. json.Number).

    For encoding.TextMarshaler it seems to hold:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    type Foo int
    
    func (s Foo) MarshalText() (text []byte, err error) {
    	return []byte("\"foo\""), nil
    }
    
    type Bar struct {
    	X Foo
    }
    
    func main() {
    	x := Bar{X: Foo(0)}
    	out, _ := json.Marshal(x)
    	fmt.Println(string(out))
    }
    

    ...gives

    foo.go:20:12: Error return value of `encoding/json.Marshal` is not checked: unsafe type `main.Foo` found
    

    However, for json.Marshaler it does not seem to hold; if MarshalText is changed to MarshalJSON in the example, thus making it implement json.Marshaler, no error is provoked. This is with 0.2.2.

  • "Not checked" issue when error passed as arg

    File t_test.go:

    package t
    
    import (
    	"encoding/json"
    	"fmt"
    	"os"
    	"testing"
    
    	"github.com/stretchr/testify/assert"
    )
    
    type Foo struct {
    	X interface{}
    }
    
    func TestSomething(t *testing.T) {
    	// 1) This provokes a "error return value not checked" error
    	assert.NoError(t, json.NewEncoder(os.Stdout).Encode(Foo{""}))
    
    	// 2) This does not
    	err := json.NewEncoder(os.Stdout).Encode(Foo{""})
    	fmt.Println(err)
    }
    

    Checking it:

    $ ./errchkjson t_test.go
    .../t_test.go:18:20: Error return value of `(*encoding/json.Encoder).Encode` is not checked: unsafe type `interface{}` found
    $ ./errchkjson -V
    errchkjson version 0.2.3
    commit: 3aae21891fb6867e0ae247403f8eb67c0573c5d5
    built at: 2022-02-08T16:17:38Z
    module version: v0.2.3, checksum: h1:97eGTmR/w0paL2SwfRPI1jaAZHaH/fXnxWTw2eEIqE0=
    goos: linux
    goarch: amd64
    

    I find it kind of inconsistent that passing the error value from Encode here to another function -- in this case the often used assert.NoError -- provokes a linter failure (see 1) above), whereas simply capturing an error to a non-underscore variable does not (see 2)). (Ironically, for this particular example, 1) actually does check it due to nature of assert.NoError, whereas 2) doesn't, but that's a sidetrack.)

    In my opinion, it would be prudent to skip reporting the error in case 1), i.e. when the returned err value is passed to some other function, because the error might actually be checked there. Just as in 2), capturing the error to a non-underscore variable means it could be checked later. As long as the tool does not make a deeper attempt to see if the error is actually checked later on, I'm not sure why it would differentiate between capturing and passing.

  • Add flag report-no-exported

    Add flag report-no-exported

    This flag is needed to disable this check in order to prevent duplicate check results with staticcheck in golangci-lint.

    See:

    • https://github.com/golangci/golangci-lint/pull/2349#issuecomment-962695413
    • https://staticcheck.io/docs/checks/#SA9005
  • Inconsistent error on similar ways to achieve json encode

    Inconsistent error on similar ways to achieve json encode

    Code sample

    type request struct {
      ID string `json:"id"`
    }
    
    r := request{ID: "ID"}
    
    body := bytes.NewBuffer(nil)
    _ = json.NewEncoder(body).Encode(r) // linter reports error on this line
    
    marshalled, _ := json.Marshal(r) // linter does not report error here
    body := bytes.NewBuffer(marshalled)
    

    json.NewEncoder(body).Encode(r) should not report error. because last 2 lines essentially does the same thing.

Remove unnecessary type conversions from Go source

About The unconvert program analyzes Go packages to identify unnecessary type conversions; i.e., expressions T(x) where x already has type T. Install

Nov 28, 2022
Go linter which checks for dangerous unicode character sequences

bidichk - checks for dangerous unicode character sequences bidichk finds dangerous unicode character sequences in Go source files. Considered dangerou

Oct 5, 2022
nostdglobals is a simple Go linter that checks for usages of global variables defined in the go standard library

nostdglobals is a simple Go linter that checks for usages of global variables defined in the go standard library

Feb 17, 2022
A tool to convert go test results to testng reports xml.

go-testng-report A tool to convert go test results to testng reports xml. Usage of testng-report: -json-report string Golang json test report (defa

Dec 8, 2021
misspelled word linter for Go comments, string literals and embedded files

gospel The gospel program lints Go source files for misspellings in comments, strings and embedded files. It uses hunspell to identify misspellings an

Aug 6, 2022
The most opinionated Go source code linter for code audit.
The most opinionated Go source code linter for code audit.

go-critic Highly extensible Go source code linter providing checks currently missing from other linters. There is never too much static code analysis.

Jan 6, 2023
[mirror] This is a linter for Go source code.

Golint is a linter for Go source code. Installation Golint requires a supported release of Go. go get -u golang.org/x/lint/golint To find out where g

Dec 23, 2022
Staticcheck - The advanced Go linter

The advanced Go linter Staticcheck is a state of the art linter for the Go programming language. Using static analysis, it finds bugs and performance

Jan 1, 2023
A Go linter to check that errors from external packages are wrapped

Wrapcheck A simple Go linter to check that errors from external packages are wrapped during return to help identify the error source during debugging.

Dec 27, 2022
A linter that handles struct tags.

Tagliatelle A linter that handles struct tags. Supported string casing: camel pascal kebab snake goCamel Respects Go's common initialisms (e.g. HttpRe

Dec 15, 2022
a simple golang SSA viewer tool use for code analysis or make a linter
a simple golang SSA viewer tool use for code analysis or make a linter

ssaviewer A simple golang SSA viewer tool use for code analysis or make a linter ssa.html generate code modify from src/cmd/compile/internal/ssa/html.

May 17, 2022
Linter for PostgreSQL

Использование Проверить миграции: oh-my-pg-linter check ./migrations/*.sql Добавить директории с дополнительными проверками (переопределение - кто пос

Nov 25, 2021
containedctx detects is a linter that detects struct contained context.Context field

containedctx containedctx detects is a linter that detects struct contained context.Context field Instruction go install github.com/sivchari/contained

Oct 22, 2022
World's spookiest linter

nosleep The world's spookiest linter nosleep is a golang-ci compatible linter which checks for and fails if it detects usages of time.Sleep. Why did y

Oct 15, 2022
Go linter to analyze expression groups: require 'import' declaration groups

grouper — a Go linter to analyze expression groups Installation

Jun 19, 2022
funcresult — a Go linter to analyze function result parameters

Go linter to analyze function result parameters: require named / unnamed function result parameters

Jan 27, 2022
Goalinter-v1: Goa framework (version1) linter

goavl: Goa framework (ver1) linter goavlは、goa version1(フォーク版)のlinterです。開発目的は、goa

Jul 28, 2022
Linter for Go's fmt.Errorf message

wrapmsg wrapmsg is Go code linter. this enforces fmt.Errorf's message when you wrap error. Example // OK ???? if err := pkg.Cause(); err != nil { re

Dec 27, 2022
Tool to populate your code with traceable and secure error codes

Essential part of any project, especially customer facing is proper and secure error handling. When error happens and customer reports it, it would be nice to know the context of the error and where it exactly occured.

Sep 28, 2022