@@ -69,6 +69,10 @@ func (errUnknown) Error() string { return "unknown" }
6969
7070func (errUnknown ) Unknown () {}
7171
72+ func (e errUnknown ) WithMessage (msg string ) error {
73+ return customMessage {e , msg }
74+ }
75+
7276// unknown maps to Moby's "ErrUnknown"
7377type unknown interface {
7478 Unknown ()
@@ -86,6 +90,10 @@ func (errInvalidArgument) Error() string { return "invalid argument" }
8690
8791func (errInvalidArgument ) InvalidParameter () {}
8892
93+ func (e errInvalidArgument ) WithMessage (msg string ) error {
94+ return customMessage {e , msg }
95+ }
96+
8997// invalidParameter maps to Moby's "ErrInvalidParameter"
9098type invalidParameter interface {
9199 InvalidParameter ()
@@ -113,6 +121,10 @@ func (errNotFound) Error() string { return "not found" }
113121
114122func (errNotFound ) NotFound () {}
115123
124+ func (e errNotFound ) WithMessage (msg string ) error {
125+ return customMessage {e , msg }
126+ }
127+
116128// notFound maps to Moby's "ErrNotFound"
117129type notFound interface {
118130 NotFound ()
@@ -127,6 +139,10 @@ type errAlreadyExists struct{}
127139
128140func (errAlreadyExists ) Error () string { return "already exists" }
129141
142+ func (e errAlreadyExists ) WithMessage (msg string ) error {
143+ return customMessage {e , msg }
144+ }
145+
130146// IsAlreadyExists returns true if the error is due to an already existing
131147// metadata item
132148func IsAlreadyExists (err error ) bool {
@@ -137,6 +153,10 @@ type errPermissionDenied struct{}
137153
138154func (errPermissionDenied ) Error () string { return "permission denied" }
139155
156+ func (e errPermissionDenied ) WithMessage (msg string ) error {
157+ return customMessage {e , msg }
158+ }
159+
140160// forbidden maps to Moby's "ErrForbidden"
141161type forbidden interface {
142162 Forbidden ()
@@ -152,6 +172,10 @@ type errResourceExhausted struct{}
152172
153173func (errResourceExhausted ) Error () string { return "resource exhausted" }
154174
175+ func (e errResourceExhausted ) WithMessage (msg string ) error {
176+ return customMessage {e , msg }
177+ }
178+
155179// IsResourceExhausted returns true if the error is due to
156180// a lack of resources or too many attempts.
157181func IsResourceExhausted (err error ) bool {
@@ -162,6 +186,10 @@ type errFailedPrecondition struct{}
162186
163187func (e errFailedPrecondition ) Error () string { return "failed precondition" }
164188
189+ func (e errFailedPrecondition ) WithMessage (msg string ) error {
190+ return customMessage {e , msg }
191+ }
192+
165193// IsFailedPrecondition returns true if an operation could not proceed due to
166194// the lack of a particular condition
167195func IsFailedPrecondition (err error ) bool {
@@ -174,6 +202,10 @@ func (errConflict) Error() string { return "conflict" }
174202
175203func (errConflict ) Conflict () {}
176204
205+ func (e errConflict ) WithMessage (msg string ) error {
206+ return customMessage {e , msg }
207+ }
208+
177209// conflict maps to Moby's "ErrConflict"
178210type conflict interface {
179211 Conflict ()
@@ -191,6 +223,10 @@ func (errNotModified) Error() string { return "not modified" }
191223
192224func (errNotModified ) NotModified () {}
193225
226+ func (e errNotModified ) WithMessage (msg string ) error {
227+ return customMessage {e , msg }
228+ }
229+
194230// notModified maps to Moby's "ErrNotModified"
195231type notModified interface {
196232 NotModified ()
@@ -206,6 +242,10 @@ type errAborted struct{}
206242
207243func (errAborted ) Error () string { return "aborted" }
208244
245+ func (e errAborted ) WithMessage (msg string ) error {
246+ return customMessage {e , msg }
247+ }
248+
209249// IsAborted returns true if an operation was aborted.
210250func IsAborted (err error ) bool {
211251 return errors .Is (err , errAborted {})
@@ -215,6 +255,10 @@ type errOutOfRange struct{}
215255
216256func (errOutOfRange ) Error () string { return "out of range" }
217257
258+ func (e errOutOfRange ) WithMessage (msg string ) error {
259+ return customMessage {e , msg }
260+ }
261+
218262// IsOutOfRange returns true if an operation could not proceed due
219263// to data being out of the expected range.
220264func IsOutOfRange (err error ) bool {
@@ -227,6 +271,10 @@ func (errNotImplemented) Error() string { return "not implemented" }
227271
228272func (errNotImplemented ) NotImplemented () {}
229273
274+ func (e errNotImplemented ) WithMessage (msg string ) error {
275+ return customMessage {e , msg }
276+ }
277+
230278// notImplemented maps to Moby's "ErrNotImplemented"
231279type notImplemented interface {
232280 NotImplemented ()
@@ -243,6 +291,10 @@ func (errInternal) Error() string { return "internal" }
243291
244292func (errInternal ) System () {}
245293
294+ func (e errInternal ) WithMessage (msg string ) error {
295+ return customMessage {e , msg }
296+ }
297+
246298// system maps to Moby's "ErrSystem"
247299type system interface {
248300 System ()
@@ -259,6 +311,10 @@ func (errUnavailable) Error() string { return "unavailable" }
259311
260312func (errUnavailable ) Unavailable () {}
261313
314+ func (e errUnavailable ) WithMessage (msg string ) error {
315+ return customMessage {e , msg }
316+ }
317+
262318// unavailable maps to Moby's "ErrUnavailable"
263319type unavailable interface {
264320 Unavailable ()
@@ -275,6 +331,10 @@ func (errDataLoss) Error() string { return "data loss" }
275331
276332func (errDataLoss ) DataLoss () {}
277333
334+ func (e errDataLoss ) WithMessage (msg string ) error {
335+ return customMessage {e , msg }
336+ }
337+
278338// dataLoss maps to Moby's "ErrDataLoss"
279339type dataLoss interface {
280340 DataLoss ()
@@ -291,6 +351,10 @@ func (errUnauthorized) Error() string { return "unauthorized" }
291351
292352func (errUnauthorized ) Unauthorized () {}
293353
354+ func (e errUnauthorized ) WithMessage (msg string ) error {
355+ return customMessage {e , msg }
356+ }
357+
294358// unauthorized maps to Moby's "ErrUnauthorized"
295359type unauthorized interface {
296360 Unauthorized ()
@@ -307,6 +371,8 @@ func isInterface[T any](err error) bool {
307371 switch x := err .(type ) {
308372 case T :
309373 return true
374+ case customMessage :
375+ err = x .err
310376 case interface { Unwrap () error }:
311377 err = x .Unwrap ()
312378 if err == nil {
@@ -324,3 +390,22 @@ func isInterface[T any](err error) bool {
324390 }
325391 }
326392}
393+
394+ // customMessage is used to provide a defined error with a custom message.
395+ // The message is not wrapped but can be compared by the `Is(error) bool` interface.
396+ type customMessage struct {
397+ err error
398+ msg string
399+ }
400+
401+ func (c customMessage ) Is (err error ) bool {
402+ return c .err == err
403+ }
404+
405+ func (c customMessage ) As (target any ) bool {
406+ return errors .As (c .err , target )
407+ }
408+
409+ func (c customMessage ) Error () string {
410+ return c .msg
411+ }
0 commit comments