It needs to keep getting better... one idea I had was that each module would define its own specialization of FAIL which would identify itself, and would chain the error IDs:
Rebol [
Name: "My Module"
Type: 'Module
Errors: https://example.com/modules/my-module/e/
]
fail '/invalid-foo [foo: 10]
The idea would be that this module's FAIL would be defined to merge that onto the Errors: URL. So you'd get an error with id https://example.com/modules/my-module/e/invalid-foo
.
What you'd want to do would be at that URL to serve a page that had english readable text as HTML, but also some kind of template that could be scraped out and used by the console to pretty print the error in a brief notation. If there was no web server or it were down (or taking too long to reply to a request), you'd just see the error as having the ID and any parameters.
I've wrestled with the question of how to merge all these desires together. e.g. what if you want to implicate a value and give it an ID, then you've got multiple things going on. Or what if the block wants to provide text as a template as well as variables? I make some notes about this in the source:
; Ultimately we might like FAIL to use some clever error-creating dialect
; when passed a block, maybe something like:
;
; fail [<invalid-key> {The key} key-name: key {is invalid}]
;
; That could provide an error ID, the format message, and the values to
; plug into the slots to make the message...which could be extracted from
; the error if captured (e.g. error/id and `error/key-name`. Another
; option would be something like:
;
; fail/with [{The key} :key-name {is invalid}] [key-name: key]
The time to start thinking about how to make all this elegant is now. We have more tools than ever!