MCPcopy
hub / github.com/larksuite/cli / handleRootError

Function handleRootError

cmd/root.go:247–303  ·  view source on GitHub ↗

handleRootError dispatches a command error to the appropriate handler and returns the process exit code. Dispatch order: 1. Typed errors from errs/ (e.g. *errs.PermissionError, *errs.APIError, *errs.SecurityPolicyError, *errs.AuthenticationError, *errs.ConfigError): render via the typed envelope wr

(f *cmdutil.Factory, err error)

Source from the content-addressed store, hash-verified

245// matching the explicit flag/subcommand guards. Flag parse errors are
246// already typed upstream by the root FlagErrorFunc.
247func handleRootError(f *cmdutil.Factory, err error) int {
248 errOut := f.IOStreams.ErrOut
249
250 // When the typed error is a need_user_authorization signal, fold in the
251 // current command's declared scopes as a Hint so the user/AI sees the
252 // concrete scope(s) to re-auth with. The hint is computed on the fly from
253 // local shortcut/service metadata — it never depends on server state.
254 if !errs.IsRaw(err) {
255 applyNeedAuthorizationHint(f, err)
256 }
257
258 // Staged dispatch: capture the typed exit code BEFORE attempting the
259 // envelope write. WriteTypedErrorEnvelope is best-effort on the wire
260 // (partial-write still returns true) so the exit code we read here is
261 // preserved even if stderr is torn — torn stderr must not downgrade
262 // typed exits 3/4/6/10 to the plain "Error:" path with exit 1.
263 // WriteTypedErrorEnvelope still returns false when err carries no
264 // Problem; in that case we fall through to the signal / plain-text paths.
265 typedExit := output.ExitCodeOf(err)
266 if output.WriteTypedErrorEnvelope(errOut, err, string(f.ResolvedIdentity)) {
267 return typedExit
268 }
269
270 // Partial-failure (batch / multi-status): the ok:false result envelope is
271 // already on stdout; set the exit code and write nothing to stderr.
272 var pfErr *output.PartialFailureError
273 if errors.As(err, &pfErr) {
274 return pfErr.Code
275 }
276
277 // Silent-exit signal (e.g. `auth check` predicate, or `update --json`):
278 // stdout already carries the result; honor the requested exit code and
279 // write nothing to stderr.
280 var bareErr *output.BareError
281 if errors.As(err, &bareErr) {
282 return bareErr.Code
283 }
284
285 // Errors reaching here are untyped: every RunE returns a typed errs.* error
286 // and flag-parse errors are typed by the root FlagErrorFunc. The remainder
287 // is either a cobra usage mistake (missing required flag, unknown command,
288 // wrong arg count), which cobra surfaces as a plain error identified by its
289 // stable text — the same external contract unknownFlagName relies on — or an
290 // untyped error that leaked past the typed boundary. Classify the former as
291 // invalid_argument (exit 2, like the explicit guards); treat the latter as an
292 // internal fault (exit 5) rather than blaming the user's input. The message
293 // is preserved either way, and the typed envelope still carries any pending
294 // deprecation notice.
295 var fallback error
296 if isCobraUsageError(err) {
297 fallback = errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err.Error())
298 } else {
299 fallback = errs.NewInternalError(errs.SubtypeUnknown, "%s", err.Error()).WithCause(err)
300 }
301 output.WriteTypedErrorEnvelope(errOut, fallback, string(f.ResolvedIdentity))
302 return output.ExitCodeOf(fallback)
303}
304

Calls 10

IsRawFunction · 0.92
ExitCodeOfFunction · 0.92
WriteTypedErrorEnvelopeFunction · 0.92
NewValidationErrorFunction · 0.92
NewInternalErrorFunction · 0.92
isCobraUsageErrorFunction · 0.85
AsMethod · 0.80
ErrorMethod · 0.45
WithCauseMethod · 0.45