Skip to content
Notifications
Clear all

Am I the only one who writes custom 'tool denied' messages to be more user-friendly?

4 Posts
4 Users
0 Reactions
2 Views
(@jackson)
Estimable Member
Joined: 1 week ago
Posts: 82
Topic starter   [#6291]

I’ve been standardizing our internal developer platform’s CLI tooling and have made a habit of customizing the error messages returned when a user lacks the necessary permissions or resources. The default output from tools like `kubectl`, `docker`, or even custom Go/Python scripts is often terse and unactionable—e.g., “access denied,” “forbidden,” or a generic HTTP 403.

I find that replacing these with structured, instructive messages significantly reduces support tickets and context-switching. For example, instead of a raw Kubernetes API forbidden error, our wrapper returns the denied verb/resource, suggests specific RBAC role names, and links to the internal runbook for access requests.

Here’s a simplified example from a Go-based tool:

```go
func checkPermission(user, action, resource string) error {
// ... permission check logic
if !authorized {
return fmt.Errorf(
"Permission denied for '%s' on '%s'.n"+
"Required role: 'platform-eng:%s-read'.n"+
"To request access, run: `iac-tool access-request --resource %s`",
user, resource, resource, resource,
)
}
return nil
}
```

The rationale is straightforward: it turns a dead-end into a guided next step. This seems obvious, yet I rarely see it in open-source tools or discussed in platform engineering circles. Is this practice uncommon? What are the trade-offs—maintenance burden, obscuring underlying system details, or something else? I’m particularly interested in how others balance clarity with security (e.g., not leaking internal resource names).


—J


   
Quote
(@jacksonw)
Estimable Member
Joined: 1 week ago
Posts: 63
 

That's a smart idea. I've only seen this done in user-facing web apps, not CLI tools. Does wrapping the tool output like this ever break something downstream, like if another script is parsing the original error format?


not a buyer, just a nerd


   
ReplyQuote
(@code_weaver_anna)
Reputable Member
Joined: 4 months ago
Posts: 163
 

It's a solid pattern, especially for internal platforms where you control the environment. The main caveat I've found is you must separate the human-friendly output from the machine-readable error code.

In our setup, we keep the original exit code intact but write the enriched guidance to stderr. That way, any automation checking for a non-zero exit status still works, and parsing scripts that rely on specific error string formats can be directed to a `--json` or `--quiet` flag that outputs the raw API error.

We've also started logging the original, unadulterated error server-side for debugging, which the user never sees. This prevents losing the technical detail while still providing actionable next steps in the terminal.


benchmark or bust


   
ReplyQuote
(@jessica8)
Estimable Member
Joined: 1 week ago
Posts: 68
 

I've tracked this exact pattern as a soft cost reduction. When we implemented similar guidance in our procurement platform's CLI, support volume for access issues dropped by about 40% over a quarter. That's measurable time saved for both developers and our platform team.

One caveat from a contracts perspective: if you're using a third-party CLI tool under a vendor agreement, modifying its output could violate terms around reverse engineering or modification. For internally-built tools, it's a clear win.

Have you quantified the reduction in ticket volume or mean time to resolution since implementing this? That data is useful for justifying the development effort to stakeholders.


Trust but verify. Then renegotiate.


   
ReplyQuote