5.1.5.1. <del> Once the agent has computed the check lists as described in sec- forming, the agent will begin performing ordinary checks and triggered checks.  For triggered checks, the agent maintains a FIFO queue, triggered check queue, which contains candidate pairs for which checks are to be sent at the next available opportunity. </del>  5.1.5.2. <del> The generation of ordinary and triggered checks is govererned by a timer, Tc.  Each active check list is associated with an instance of Tc, and whenever Tc for a given check list fires a check is performed for a candidate pair within that check list. The value of Tc is Ta*N seconds, where N is the number of active check lists.  Whenver the number of active check lists change, the agent SHOULD re-calculate the Tc value.  Multiplying by N allows this aggregate check throughput to be split between all active check lists.  Tc associated with the first check list fires immediately, causing the agent to start performing connectivity checks as soon as the intitial states of the candidate pairs in each check list have been calculated. Implementations SHOULD spread out the starting of the Tc timers associated with each check list, so that Tc for each check list do not fire at the same time. Based on local policy, an agent MAY set the Tc value to a number bigger than described above, in order for Tc to fire less frequently. 5.1.5.3. When Tc for a given check list fires, the agent will perform a check for a candidate pair within that check list as follows: If the triggered check queue contains one or more candidate pairs, the agent removes the top pair from the queue, performs a connectivity check on that pair and puts the candidate pair state to In-Progress; or If the triggered check queue is empty, and if there are one or more candidate pairs in the Waiting state, the agent selects the highest- priority candidate pair in the Waiting state, performs a </del>  connectivity check on that pair and puts the candidate pair par state to In-Progress; or <del> If there is no candidate pair in the Waiting state, in any of the check lists, and if there are one or more candidate pairs in the Frozen state, the agent selects the highest-priority candidate pair in the Frozen state, performs a connectivity check on that pair and puts the candidate pair par state to In-Progress; or If there is no candidate in the Waiting or Frozen state, the agent MUST terminate timer Tc for that check list and re-calculate Tc for the remaining active check lists. Once a candidate pair has been selected, the agent performs the check </del>  by sending a STUN request from the base associated with the local candiditate of the pair to the remote candidiate of the pair, as described in sec-send-check. Based on local policy, an agent MAY choose to terminate perfoming the <del> connectivity checks for one or more active checks lists (and terminate the Tc associated with those check lists) at any time. </del>  To compute the message integrity for the check, the agent uses the remote username fragment and password learned from the candidate known directly by the agent for its own candidate. The Initiator performs the ordinary checks on receiving the candidate <del> information from the Peer (responder) and having formed the checklists.  On the other hand the responding agent either performs the triggered or ordinary checks as described above. </del>  5.2.

Removal of timer Tc. Instead timer Ta is used to trigger connectivity checks. Whenever Ta fires, one check list is selected, and a connectivity check is performed for a candidate pair within that check list.

5.1.5.1.  <ins> Once the agent has computed the check lists and created the CHECK LIST SET, as described in sec-forming, the agent will begin performing connectivity checks (ordinary and triggered).  For triggered connectivity checks, the agent maintains a FIFO queue for each check list, called the triggered check queue, which contains candidate pairs for which checks are to be sent at the next available opportunity. </ins> 5.1.5.2.  <ins> The generation of ordinary and triggered connectivity checks is govererned by timer Ta.  As soon as the initial states for the candidiate pairs in the CHECK LIST SET have been set, a check is performed for a candidate pair within the first check list in the Running state, following the procedures in sec-connectivity_check. After that, whenever Ta fires the next check list in the Running state in the CHECK LIST SET is selected, and a check is performed for a candidiate within that check list.  After the last check list in the Running state in the CHECK LIST SET has been processed, the first check list is selected again.  Etc. NOTE: When timer Ta fires, and the agent processes a check list, if no check is performed for a pair in the check list (based on the rules below), the agent can immediately select the next check list in the Running state, without waiting for timer Ta to expire again. Whenever Ta fires, the agent will perform a check for a candidate pair within the selected check list as follows: If the triggered check queue associated with the check list contains one or more candidate pairs, the agent removes the top pair from the queue, performs a connectivity check on that pair and puts the candidate pair state to In-Progress; or If the triggered check queue associated with the check list is empty, and if there are one or more candidate pairs in the Waiting state, the agent selects the highest-priority candidate pair (if there are multiple pairs with the same priority, the pair with the lowest component ID is selected) in the Waiting state, performs a </ins> connectivity check on that pair and puts the candidate pair par state to In-Progress; or  <ins> If there is no candidate pair in the Waiting state, and if there are one or more pairs in the Frozen state, for each pair in the Frozen state the the agent checks the foundation associated with the pair.  For a given foundation, if there is no pair (in any check list in the CHECK LIST SET) in the Waiting or In-Progress state, the agent performs a connectivity check on the pair and puts the pair state to In-Prograss.  If, for the same foundation, there are one or more pairs in the Waiting or In-Progress state, (in any check list in the CHECK LIST SET) the agent does not perform a connectivity check on the pair. Once the agent has selected a candidate pair, for which a connectivity check is to be performed, the agent performs the check </ins> by sending a STUN request from the base associated with the local candiditate of the pair to the remote candidiate of the pair, as described in sec-send-check. Based on local policy, an agent MAY choose to terminate perfoming the  <ins> connectivity checks for one or more checks lists in the CHECK LIST SET at any time.  However, only the controlling agent is allowed to conclude ICE (sec-conclude). </ins> To compute the message integrity for the check, the agent uses the remote username fragment and password learned from the candidate known directly by the agent for its own candidate. The Initiator performs the ordinary checks on receiving the candidate  <ins> information from the Peer (responder) and having formed the check lists.  On the other hand the responding agent either performs the triggered or ordinary checks as described above. </ins> 5.2.


Running state in the CHECK LIST SET has been processed, the first CHECK LIST is selected again.  Etc. <del> NOTE: When timer Ta fires, and the agent processes a CHECK LIST, if no check is performed for a pair in the CHECK LIST (based on the rules below), the agent can immediately select the next CHECK LIST in the Running state, without waiting for timer Ta to expire again. </del> Whenever Ta fires, the agent will perform a check for a candidate <del> pair within the selected CHECK LIST as follows: </del>  If the TRIGGERED CHECK QUEUE associated with the CHECK LIST contains one or more candidate pairs, the agent removes the top <del> pair from the queue, performs a connectivity check on that pair and puts the candidate pair state to In-Progress; or If the TRIGGERED CHECK QUEUE associated with the CHECK LIST is empty, and if there are one or more candidate pairs in the Waiting state, the agent selects the highest-priority candidate pair (if there are multiple pairs with the same priority, the pair with the lowest component ID is selected) in the Waiting state, performs a connectivity check on that pair and puts the candidate pair par state to In-Progress; or </del>  If there is no candidate pair in the Waiting state, and if there are one or more pairs in the Frozen state, for each pair in the <del> Frozen state the the agent checks the foundation associated with the pair.  For a given foundation, if there is no pair (in any CHECK LIST in the CHECK LIST SET) in the Waiting or In-Progress state, the agent performs a connectivity check on the pair and puts the pair state to In-Prograss.  If, for the same foundation, there are one or more pairs in the Waiting or In-Progress state, (in any CHECK LIST in the CHECK LIST SET) the agent does not perform a connectivity check on the pair. </del>  Once the agent has selected a candidate pair, for which a connectivity check is to be performed, the agent performs the check

Alternate version of PR . Rather than structuring the Ta procedures as: If , do , or; If , do , or; ... This PR structures them more like pseudocode, with the ability for multiple steps to be run in the same Ta cycle, reducing some text duplication.

Running state in the CHECK LIST SET has been processed, the first CHECK LIST is selected again.  Etc.  Whenever Ta fires, the agent will perform a check for a candidate  <ins> pair within the selected CHECK LIST by performing the following steps: </ins> If the TRIGGERED CHECK QUEUE associated with the CHECK LIST contains one or more candidate pairs, the agent removes the top  <ins> pair from the queue, performs a connectivity check on that pair, puts the candidate pair state to In-Progress, and aborts the subsequent steps. </ins> If there is no candidate pair in the Waiting state, and if there are one or more pairs in the Frozen state, for each pair in the  <ins> Frozen state the agent checks the foundation associated with the pair.  For a given foundation, if there is no pair (in any CHECK LIST in the CHECK LIST SET) in the Waiting or In-Progress state, the agent puts the candidate pair state to Waiting and continues with the next step. If there are one or more candidate pairs in the Waiting state, the agent selects the highest-priority candidate pair (if there are multiple pairs with the same priority, the pair with the lowest component ID is selected) in the Waiting state, performs a connectivity check on that pair, puts the candidate pair par state to In-Progress, and abort the subsequent steps. If this step is reached, no check could be performed for the selected CHECK LIST.  So, without waiting for timer Ta to expire again, select the next CHECK LIST in the Running state and return to step #1.  If this happens for every single CHECK LIST in the Running state, meaning there are no remaining candidate pairs to perform connectivity checks for, abort these steps. </ins> Once the agent has selected a candidate pair, for which a connectivity check is to be performed, the agent performs the check


This specification makes use of the following additional terminology:  An agent is the protocol implementation involved in the ICE candidate exchange.  There are two agents involved in a typical candidate exchange.

Not sure this is correct. ICE session is something that continues until ufrag/passwords change. The same candidates can be re-used across multiple ICE sessions.
I think better definition will be: An ICE session consists of all ICE-related actions starting with the candidate gathering, followed by the interactions (candidate exchange, connectivity checks, nominations and keep-alives) between the ICE agents until all the candidates are released or ICE-restart is initiated by ufrag/password change.
Roman's suggestion looks good.
I think the current proposed explanation (one with more details) is good. Would suggest merging this.
My suggestion is to merge, submit a new version, and then continue working on Peter's issues.
Why not just say an ICE session is all ICE activity tied to a candidate exchange with a specific ufrag/pwd? Every time you do a candidate exchange with a new ufrag/pwd, you have a new ICE session. I don't think we need to say all the rest.

This specification makes use of the following additional terminology: <ins> An ICE session consists of all ICE-related actions starting with the candidate gathering, followed by the interactions (candidate exchange, connectivity checks, nominations and keep-alives) between the ICE agents until all the candidates are released or ICE-restart is triggered. </ins> An agent is the protocol implementation involved in the ICE candidate exchange.  There are two agents involved in a typical candidate exchange.


address and port) in addition to the ICE parameters. STUN connectivity checks between agents are authenticated using the <del> short-term credential mechanism defined for STUN [RFC5389].  This mechanism relies on a username and password that are exchanged through protocol machinery between the client and server.  The username part of this credential is formed by concatenating a username fragment from each agent, separated by a colon.  Each agent also provides a password, used to compute the message integrity for requests it receives.  The username fragment and password are exchanged between the peers.  In addition to providing security, the username provides disambiguation and correlation of checks to media streams.  See Appendix B.4 for motivation. </del>  If the initiating agent is a lite implementation, it MUST indicate this when sending its candidates .

It looks like two references didn't get translated into xml2rfc xref tags when RFC 5245 got imported.
LGTM! Thanks!

address and port) in addition to the ICE parameters. STUN connectivity checks between agents are authenticated using the  <ins> short-term credential mechanism defined for RFC5389.  This mechanism relies on a username and password that are exchanged through protocol machinery between the client and server.  The username part of this credential is formed by concatenating a username fragment from each agent, separated by a colon.  Each agent also provides a password, used to compute the message integrity for requests it receives.  The username fragment and password are exchanged between the peers.  In addition to providing security, the username provides disambiguation and correlation of checks to media streams.  See sec-why-uname for motivation. </ins> If the initiating agent is a lite implementation, it MUST indicate this when sending its candidates .


The combination of an IP address and transport protocol (such as UDP or TCP) port. <del> When ICE is used to setup multimedia sessions, the data is transported using some protocol.  Media data is usually transported over RTP, and a media data stream composes of a stream of RTP packets.  Data session refers to data packets that are exchanged between the peer on the path created and tested with ICE. </del>  A transport address that is a potential point of contact for receipt of data.  Candidates also have properties -- their type A component is a piece of a data stream.  A data stream may require multiple components, each of which has to work in order <del> for the data stream as a while for work.  For media data streams based on RTP, unless RTP and RTCP are multiplexed in the same port, there are two components per media data stream -- one for RTP, and one for RTCP.  A component has a candidate pair, which cannot be used by other components </del>  A candidate obtained by binding to a specific port from an IP address on the host.  This includes IP addresses on physical a specific component for which it is a candidate. Each component has an ID assigned to it, called the component ID. <del> For RTP-based media data streams, unless both RTP and RTCP are multiplexed in the same UDP port (RTP/RTCP multiplexing), the RTP itself has a component ID of 1, and RTCP a component ID of 2.  In case of RTP/RTCP multiplexing, a component ID of 1 is used for both RTP and RTCP. </del>  When candidates are obtained, unless the agent knows for sure that RTP/RTCP multiplexing will be used (i.e. the agent knows that the However, absence of a component ID 2 as such does not imply use of RTCP/RTP multiplexing, as it could also mean that RTCP is not used. <del> For other than RTP-based streams, use of multiple components is </del>  discouraged since using them increases the complexity of ICE processing.  If multiple components are needed, the component IDs SHOULD start with 1 and increase by 1 for each component. Allocate response will provide the agent with a server reflexive candidate (obtained from the mapped address) and a relayed candidate in the XOR-RELAYED-ADDRESS attribute.  If the Allocate request is <del> rejected because the server lacks resources to fulfil it, the agent </del>  SHOULD instead send a Binding request to obtain a server reflexive candidate.  A Binding response will provide the agent with only a server reflexive candidate (also obtained from the mapped address). determine whether to use one address or the other. Each component has an ID assigned to it, called the component ID. <del> For RTP-based media data streams, unless RTCP is multiplexed in the same port with RTP, the RTP itself has a component ID of 1, and RTCP a component ID of 2.  If an agent is using RTCP without multiplexing, </del>  it MUST obtain candidates for it.  However, absence of a component ID 2 as such does not imply use of RTCP/RTP multiplexing, as it could also mean that RTCP is not used. 7.3.1.4. <del> Next, the agent constructs a pair whose local candidate is equal to the transport address (as seen by the agent) on which the STUN request was received, and a remote candidate equal to the source transport address where the request came from (which may be the peer reflexive remote candidate that was just learned).  The local candidate will either be a host candidate (for cases where the request was not received through a relay) or a relayed candidate (for cases where it is received through a relay).  The local candidate can never be a server reflexive candidate.  Since both candidates are known to the agent, it can obtain their priorities and compute the candidate pair priority.  This pair is then looked up in the check list.  There can be one of several outcomes: </del>  If the pair is already on the check list: If the controlled agent receives a Binding request with the USE- CANDIDATE attribute set, and if the ICE agent accepts the request, <del> the agent constructs a candidate pair whose local candidate is equal to the transport address on which the request was received, and whose remote candidate is equal to the source transport address of the request that was received.  This candidate pair is assigned an arbitrary priority, and placed into the valid list of the associated check list.  The agent sets the nominated flag for that pair to true. </del>  Once the nominated flag is set for a component of a data stream, it concludes the ICE processing for that component.  See sec-conclude. Eventually, if the nominations succeed, both the controlling and controlled agents will have a single nominated pair in the valid list for each component of the data stream.  Once an ICE agent sets the <del> state of the check list is set to Completed (when there is a nominated pair for each component of the data stream), that pair becomes the selected pair for that agent, and is used for sending and receiving data for that component of the data stream. </del>  If an agent is not able to produce selected pairs for a data stream, the agent MUST take proper actions for informing the other agent, and selected pairs have been produced for a data stream. It is RECOMMENDED that, when an agent receives an RTP packet with a <del> new source or destination IP address for a particular media data </del>  stream, that the agent re-adjust its jitter buffers. RFC 3550 RFC3550 describes an algorithm in Section 8.2 for detecting synchronization source (SSRC) collisions and loops.  These algorithms are based, in part, on seeing different source transport addresses with the same SSRC.  However, when ICE is used, such changes will <del> sometimes occur as the media data streams switch between candidates. An agent will be able to determine that a media data stream is from the same peer as a consequence of the STUN exchange that proceeds media data transmission.  Thus, if there is a change in source transport address, but the media data packets come from the same peer agent, this MUST NOT be treated as an SSRC collision. </del>  14.

Fix spelling: Replace “fulfil” with “fulfill” Fix grammar: “agent sets the state…is set to Completed“ with “agent sets the state…to Completed” Make consistent with recent changes: Replace “candidate is equal to the transport address” with “candidate has the transport address” Replace “multimedia session” with “data session” Replace “media data stream” with “RTP/RTCP data stream” or just “data stream” Replace “media data” with “data”

The combination of an IP address and transport protocol (such as UDP or TCP) port.  <ins> When ICE is used to setup data sessions, the data is transported using some protocol.  Media is usually transported over RTP, composed of a stream of RTP packets.  Data session refers to data packets that are exchanged between the peer on the path created and tested with ICE. </ins> A transport address that is a potential point of contact for receipt of data.  Candidates also have properties -- their type A component is a piece of a data stream.  A data stream may require multiple components, each of which has to work in order  <ins> for the data stream as a whole to work.  For RTP/RTCP data streams, unless RTP and RTCP are multiplexed in the same port, there are two components per data stream -- one for RTP, and one for RTCP.  A component has a candidate pair, which cannot be used by other components </ins> A candidate obtained by binding to a specific port from an IP address on the host.  This includes IP addresses on physical a specific component for which it is a candidate. Each component has an ID assigned to it, called the component ID.  <ins> For RTP/RTCP data streams, unless both RTP and RTCP are multiplexed in the same UDP port (RTP/RTCP multiplexing), the RTP itself has a component ID of 1, and RTCP a component ID of 2.  In case of RTP/RTCP multiplexing, a component ID of 1 is used for both RTP and RTCP. </ins> When candidates are obtained, unless the agent knows for sure that RTP/RTCP multiplexing will be used (i.e. the agent knows that the However, absence of a component ID 2 as such does not imply use of RTCP/RTP multiplexing, as it could also mean that RTCP is not used.  <ins> For other than RTP/RTCP streams, use of multiple components is </ins> discouraged since using them increases the complexity of ICE processing.  If multiple components are needed, the component IDs SHOULD start with 1 and increase by 1 for each component. Allocate response will provide the agent with a server reflexive candidate (obtained from the mapped address) and a relayed candidate in the XOR-RELAYED-ADDRESS attribute.  If the Allocate request is  <ins> rejected because the server lacks resources to fulfill it, the agent </ins> SHOULD instead send a Binding request to obtain a server reflexive candidate.  A Binding response will provide the agent with only a server reflexive candidate (also obtained from the mapped address). determine whether to use one address or the other. Each component has an ID assigned to it, called the component ID.  <ins> For RTP/RTCP data streams, unless RTCP is multiplexed in the same port with RTP, the RTP itself has a component ID of 1, and RTCP a component ID of 2.  If an agent is using RTCP without multiplexing, </ins> it MUST obtain candidates for it.  However, absence of a component ID 2 as such does not imply use of RTCP/RTP multiplexing, as it could also mean that RTCP is not used. 7.3.1.4.  <ins> Next, the agent constructs a pair whose local candidate has the transport address (as seen by the agent) on which the STUN request was received, and a remote candidate equal to the source transport address where the request came from (which may be the peer reflexive remote candidate that was just learned).  The local candidate will either be a host candidate (for cases where the request was not received through a relay) or a relayed candidate (for cases where it is received through a relay).  The local candidate can never be a server reflexive candidate.  Since both candidates are known to the agent, it can obtain their priorities and compute the candidate pair priority.  This pair is then looked up in the check list.  There can be one of several outcomes: </ins> If the pair is already on the check list: If the controlled agent receives a Binding request with the USE- CANDIDATE attribute set, and if the ICE agent accepts the request,  <ins> the agent constructs a candidate pair whose local candidate has the transport address on which the request was received, and whose remote candidate is equal to the source transport address of the request that was received.  This candidate pair is assigned an arbitrary priority, and placed into the valid list of the associated check list.  The agent sets the nominated flag for that pair to true. </ins> Once the nominated flag is set for a component of a data stream, it concludes the ICE processing for that component.  See sec-conclude. Eventually, if the nominations succeed, both the controlling and controlled agents will have a single nominated pair in the valid list for each component of the data stream.  Once an ICE agent sets the  <ins> state of the check list to Completed (when there is a nominated pair for each component of the data stream), that pair becomes the selected pair for that agent, and is used for sending and receiving data for that component of the data stream. </ins> If an agent is not able to produce selected pairs for a data stream, the agent MUST take proper actions for informing the other agent, and selected pairs have been produced for a data stream. It is RECOMMENDED that, when an agent receives an RTP packet with a  <ins> new source or destination IP address for a particular RTP/RTCP data </ins> stream, that the agent re-adjust its jitter buffers. RFC 3550 RFC3550 describes an algorithm in Section 8.2 for detecting synchronization source (SSRC) collisions and loops.  These algorithms are based, in part, on seeing different source transport addresses with the same SSRC.  However, when ICE is used, such changes will  <ins> sometimes occur as the data streams switch between candidates.  An agent will be able to determine that a data stream is from the same peer as a consequence of the STUN exchange that proceeds media data transmission.  Thus, if there is a change in source transport address, but the media data packets come from the same peer agent, this MUST NOT be treated as an SSRC collision. </ins> 14.


All endpoints MUST send keepalives for each media session.  These keepalives serve the purpose of keeping NAT bindings alive for the <del> media session.  These keepalives MUST be sent even if ICE is not being utilized for the session at all.  The keepalive SHOULD be sent using a format that is supported by its peer.  ICE endpoints allow for STUN-based keepalives for UDP streams, and as such, STUN keepalives MUST be used when an agent is a full ICE implementation and is communicating with a peer that supports ICE (lite or full). If the peer does not support ICE, the choice of a packet format for keepalives is a matter of local implementation.  A format that allows packets to easily be sent in the absence of actual media content is RECOMMENDED.  Examples of formats that readily meet this goal are RTP No-Op I-D.ietf-avt-rtp-no-op, and in cases where both sides support it, RTP comfort noise RFC3389.  If the peer doesn't support any formats that are particularly well suited for keepalives, an agent SHOULD send RTP packets with an incorrect version number, or some other form of error that would cause them to be discarded by the peer. </del>  If there has been no packet sent on the candidate pair ICE is using for a media component for Tr seconds (where packets include those defined for the component (RTP or RTCP) and previous keepalives), an <del> agent MUST generate a keepalive on that pair.  Tr SHOULD be configurable and SHOULD have a default of 15 seconds.  Tr MUST NOT be configured to less than 15 seconds.  Alternatively, if an agent has a dynamic way to discover the binding lifetimes of the intervening NATs, it can use that value to determine Tr.  Administrators deploying ICE in more controlled networking environments SHOULD set Tr to the longest duration possible in their environment. If STUN is being used for keepalives, a STUN Binding Indication is </del>  used RFC5389.  The Indication MUST NOT utilize any authentication mechanism.  It SHOULD contain the FINGERPRINT attribute to aid in demultiplexing, but SHOULD NOT contain any other attributes.  It is

The usage of no-op mechanism and RTP comfort noise mechanism for keepalives have been removed. Also, the keepalive procedures when communicating with a non-ICE peer, and when ICE is not used at all, have been removed.

All endpoints MUST send keepalives for each media session.  These keepalives serve the purpose of keeping NAT bindings alive for the  <ins> media session.  The keepalives SHOULD be sent using a format that is supported by its peer.  ICE endpoints allow for STUN-based keepalives for UDP streams, and as such, STUN keepalives MUST be used when an agent is a full ICE implementation and is communicating with a peer that supports ICE (lite or full). </ins> If there has been no packet sent on the candidate pair ICE is using for a media component for Tr seconds (where packets include those defined for the component (RTP or RTCP) and previous keepalives), an  <ins> agent MUST generate a keepalive on that pair.  ICE endpoints SHOULD use a Tr value of 15 seconds, but MAY use another value, e.g. based on configuration or network/NAT characteristics.  For example, if an agent has a dynamic way to discover the binding lifetimes of the intervening NATs, it can use that value to determine Tr. Administrators deploying ICE in more controlled networking environments SHOULD set Tr to the longest duration possible in their environment.  ICE endpoints MUST NOT use a Tr value smaller than 15 seconds. When STUN is being used for keepalives, a STUN Binding Indication is </ins> used RFC5389.  The Indication MUST NOT utilize any authentication mechanism.  It SHOULD contain the FINGERPRINT attribute to aid in demultiplexing, but SHOULD NOT contain any other attributes.  It is


A problem details object can have the following members: <del> "type" (string) - A URI reference RFC3986 that identifies the problem type.  This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML HTML5).  When this member is not present, its value is assumed to be "about:blank". "title" (string) - A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see I-D.ietf-httpbis-semantics, Section 12.1). "status" (number) - The HTTP status code (I-D.ietf-httpbis- semantics, Section 15) generated by the origin server for this occurrence of the problem. "detail" (string) - A human-readable explanation specific to this occurrence of the problem. "instance" (string) - A URI reference that identifies the specific occurrence of the problem.  It may or may not yield further information if dereferenced. Consumers MUST use the "type" string as the primary identifier for the problem type; the "title" string is advisory and included only for users who are not aware of the semantics of the URI and do not have the ability to discover them (e.g., offline log analysis). Consumers SHOULD NOT automatically dereference the type URI. </del>  The "status" member, if present, is only advisory; it conveys the HTTP status code used for the convenience of the consumer. persist without HTTP information.  Generic HTTP software will still use the HTTP status code.  The "detail" member, if present, ought to focus on helping the client correct the problem, rather than giving debugging information. extensions are more suitable and less error-prone ways to obtain such information. <del> Note that both "type" and "instance" accept relative URIs; this means that they must be resolved relative to the document's base URI, as per RFC3986, Section 5. 3.2. </del>  Problem type definitions MAY extend the problem details object with additional members.

This necessitated rearranging the section on members for clarity. Also, "Consumers MUST use the 'type' string..." was changed to "Consumers MUST use the 'type' URI..." for consistency.
Pulling this conversation out of : Relative path URLs like act counter-intuitively. At first glance, they are some kind of api-global identifier, but in fact they should be considered as a path relative to the current resource, so an response from is a totally distinct error type to an response from . That is likely not what anybody intended. In addition, it appears that almost all implementations of this spec do not take that into account, parsing and comparing type URIs directly, and never using the resource URI that returned it at all. This is a likely footgun for users implementing this spec, and there are easy better alternatives (see ), so we should highlight that.
Minor but important nitpick - sorry! Those two examples are actually the same - the resolved value is . The relative path in this case would replace the final path segment, not append to it. A better example could be vs . This does fantastically highlight why relative URLs are difficult to use though :)
Haha, good catch! The same would apply if I'd included a trailing slash too I think: . Glad I've successfully illustrated my point though :facepalm:
I think this was addressed by - can we close?
Yes, I think so! :+1:
Pulling this conversation out of : It's clear that there's demand for error codes scoped to the API, without creating documentation pages for each code and linking to them in the field. There are many ways that implementers could do this, from linking to non-existent URLs to URNs to tags URIs, etc. It would be useful if the specification included examples of this, and made a clear recommendation for this case.
We (well, mostly NAME have made some good progress on the other issues raised out of but we haven't looked at this one yet. As strawman to get this moving, how about: we register a URN namespace id, and we recommend that non-dereferenceable URIs should be URNs using that, namespaced with an appropriate domain and raw type id, for example: . Would that work? It would give us a clear solution to recommend, which is explicit but easy to read, with minimal extra complexity or overhead for implementers (imo). I don't have examples, but I suspect there are other standards elsewhere that would appreciate having a problem id namespace for URNs as well. I don't love using a domain for namespacing a non-locator, but I think some namespacing is preferable, and I'm not sure what other namespaces would be suitable. Alternatives very welcome :smile:
We penciled in the URI prefix for registered types as "URL" in , but that was not finalised. I think registering one or more problems as exemplars is a good path forward for this and other issues (e.g., as discussed in ). We need to be very careful to set a good example in them, which means we need good candidates; I'm thinking 'JSON Validation Error' and 'XML Validation Error' might be appropriate (perhaps along with corresponding wellformedness errors). If we choose a urn, I suspect there will be considerable pressure to use or something similar, as per .
my understanding of the "urn:ietf:params" namespace is that it is meant to be used for parameters managed/defined by IETF specs. i think the original's suggestion intent was to have a "safe prefix" for a namespace which then would be "unmanaged" with some conventions around that, such as using domains names. i think the idea of giving examples (and even a suggested namespace along with conventions for using it) is a good one. that way we can clearly support both scenarios: if you're planning on making documentation available, use a resolvable URI but keep in mind that this best should be managed in a way so that it works for a good number of years. if you're planning on just identifying problem types, use a non-resolvable URI, and here's a recipe for doing it.
:+1: exactly I think is relevant in that it would be helpful to everybody if we can follow our own recommendations in our own problem id registry, but it's otherwise independent.
the difficulty may be that IETF has an institutional approach for managing parameters (urn:ietf:params:http-problems mentioned by NAME above), whereas most orgs minting problem types probably won't have one and won't create one. which may lead to us to saying three things about what kind of URI to use: check out common problem types registered under urn:ietf:params:http-problems and consider reusing one if it fits. use URIs when creating dereferencable problem type identifiers. when using non-dereferencable problem type identifiers be clear about that by using non-dereferencable URIs, and here's an URN-based recipe how to do that.
Ah, I see, ok. Yes, that makes sense, and given that the 3 part recommendation seems reasonable to me.
to be used for parameters managed/defined by IETF specs. No, it's for parameter name spaces managed by IETF documents -- which this would be. We could also give an example that uses a URI.
that's what i wanted to say. so these URIs/examples would just cover the common problem types that would be managed by the spec. which then would be for those other types that people/orgs are minting and where they say these are not resolvable, right? i think for those terry proposed a URN namespace instead of tag URIs, but either way it simply would help to state the use case ("your own types, not intended to be resolvable") and provide a recipe ("here's one way to do it"). the main point seems to be: the spec should mention both "common types" which may even get a registry, and "private types" which probably are using a different namespace, and we could suggest one pattern for doing that.
In NAME Twitter , this was the only and much-repeated comment. I'll copy some of the posts from there in here: URL URL (me): URL URL This confusion is also repeated frequently elsewhere, e.g. it's the top complaint in unrelated of the standard. Meanwhile URL (on the first page of results for "problem details standard") says: Arguably is the most useful field in the standard, so this is not a good result. I think it'd be useful to discuss this, at least to document the reasoning here more clearly, and to consider alternative approaches and/or alternative ways to make type URIs easier for devs.
I'll add a separate comment, from my personal point of view: As far as I understand, the goal is to encourage namespacing of error types, is that right? Are there other benefits that the URI provides? Imo, it's quite unusual as a web API response - it reminds me of a more rigorous XML-style API design with careful namespacing of all identifiers, rather than the less rigorous JSON formats that are now more common. It feels inconsistent with other HTTP standards too, e.g. link relation types do not use URIs as type identifiers. Similarly, while API developers will be familiar with HTTP URLs, a great many (I believe) are not familiar with the URIs more generally and the other formats available (e.g. Erik tag URIs - I'd like to think I'm reasonably interested in the standards and tools available, and I'd never even heard of these!). Recommending that unique id for an error type to be a documentation URL is problematic, because documentation URLs may well change and unique ids must not (yes, old documentation URLs should redirect to new ones, but there's not always a 1-1 mapping of URLs, it's messy to keep using the incorrect URL/domains in this field, and we all know this isn't always true/possible anyway). Having a separate optional documentation URL instead would be more useful imo. Right now, it's not guaranteed that a type URL is dereferenceable, so applications must effectively treat it as never dereferenceable. A separate field (or indeed link relation) would be defined as such, making it usable in many more cases. Making it an opaque string instead would still allow for the use of URIs for namespacing if desired, and we could still recommend that users do that without necessarily requiring that.
URIs can be dereferenceable. That's a pretty significant feature. Perhaps the RFC can mention the possibility to use HTTP's features to make URIs stable, such as using stable API URLs in that perform HTTP redirects towards the (ever changing) documentation. I think that's a horrible suggestion. Big . Opaque strings are already allowed. I don't really understand the problem here. The last paragraph of states the following: This means is perfectly valid.
The type field currently has to be a URI Reference. This means it can either be a URI or a relative-ref. This in turn means that you can use almost any bare string in there and still be following the letter of the RFC, even if not the intention. I've seen examples of exactly that - with values for that are actually just error codes because, strictly speaking, they are legal relative URIs that just don't happen to resolve to anything. Personally, I've no major problem with that, except that it makes it much more likely to get collisions across APIs - with two different APIs using the same type "URI" to mean different things. I can imagine there are some big benefits to be obtained if the URI is dereferenceable though. Things like getting human-readable documentation from it, or a JSON Schema that describes the shape of the problem details. Dereferencing an URI might take you directly to the log messages for what went wrong (for internal APIs only!) But equally, saying that these must be dereferenceable is potentially quite a big hurdle for many smaller developers that would potentially either stop them using this or else just have them ignore the difficult bits.
Currently, is not dereferenceable though, explicitly. The RFC says "Consumers SHOULD NOT automatically dereference the type URI", and has no mechanism to know when it could be dereferenceable. In effect, it's manually dereferenceable only. Imo it would be more useful there was such a mechanism, or indeed a separate always-dereferenceable URL elsewhere. Could you be more specific about why? I see - that's not communicated at all right now! If that's intended, I think it would be useful to communicate that better in the spec. Currently every single example in the spec is an absolute HTTP URL, all discussion of the standard elsewhere does the same, and I think the comments above clearly show that other options aren't widely recognized. Illustrating that a classic error code string is allowed but a full URL is encouraged would resolve quite a few of the concerns there I think.
Race condition posting there, sorry - to reply to NAME Ok, I think this agrees with NAME point, and this is likely a communication issue rather than a change to the format itself them. Agree, I'd love to have a documented way to know when that's possible. Making it possible to include a dereferenceable URL explicitly but optionally would be a big help.
that wouldn't be great as a pattern to recommend. the actual error URI in this case is the relative URI resolved against the URI of the context (in this case, the resource that returned the error). so while this is technically legal, it's pretty bad in terms of utility when it comes to implementations properly handling the type values as URIs.
Yeah, we both posted the same thing at the same time :) And yes, I think we are both saying the exact same thing. Edit - looking at timestamps it wasn't the exact same time. Just my window hadn't updated at the time! Maybe I'm wrong, but I've always read that with the emphasis on "automatically". As in - dereference only when needed and not always. And I've read it like that because some scenarios that would cause errors to be returned would also mean that the URI that is the problem type would also fail to resolve, and potentially cause more problems for the service (DoS attack or similar.) Equally, especially for , it could be that the intention is for humans to dereference it and not computers. For example, I've started using type values similar to for cases where the status code alone tells you everything, but I still want to include a Problem response. There's also a problem that not all clients are capable of dereferencing all URIs. For example, if it's an "http" scheme then you need to be able to make HTTP requests to the target server. Not all clients can do that, especially if they are on a closed network.
implementations properly handling the type values as URIs. NAME Would it be reasonable then to also include examples of URIs which are not URLs? e.g. as you suggested on Twitter.
i think what we have clearly established is that if 'type' remains to be defined as a URI, better guidance would be a good idea.
just means there should not be automatic dereferencing. Non-automatic dereferencing such as making the URI a user-clickable link, or a developer copying and pasting it into a browser, is perfectly valid, though. That should perhaps be made more explicit. works perfectly well for documentation. Decoupling the problem type from the problem type's documentation when the former can redirect to the latter just adds confusion, possible inconsistencies, and errors, imho. But it is. As I wrote above, the last paragraph of states the following: … I agree that can be emphasized closer to the definition of and not just as a seemingly unrelated paragraph. A way to accomplish this would be to promote each member in section 3.1 to its own section so the spec can use more than one paragraph to describe each member. Examples are non-normative. To understand the spec, you have to read the normative text. An example containing with a relative URI would be a good addition, though. Agreed. I think URIs sounds like a bad fit for as they are more of a human readable alternative to UUID.
Hmm, yes, so is actually quite very bad. Doing so is most likely a mistake: if a developer returns as an error type from two different resources, clients must treat those as distinct types, relative to different base URLs. That's quite surprising! This is probably not what the dev intended, and code that does treat them as equivalent automatically is not following the spec. It looks like this is a real problem: even the most popular makes this mistake. It matches problem detail classes automatically by comparing the value, and never uses a base URL or relative resolution for type values anywhere. I suspect that it's not alone in this, and that using bare strings as global error types will work in many places, incorrectly. Imo, tag URIs are a good improvement, but they're still not great. The most convenient equivalent tag we'd be suggesting is probably . It's obvious that it isn't dereferenceable, which is good, but it's still an unusual error code format. There's clearly friction with URIs error codes right now, and widespread patterns of not using URIs for error identifiers in every existing API I can find (e.g. , , ). Instead, they all use opaque string identifiers decoupled from documentation URLs. From my perspective and I think from the feedback above, it would be useful to have a standard that supported existing common error API patterns. This doesn't preclude namespacing where that's useful, it just doesn't enforce it. Ok, I see how this sentence is referring to fully automated dereferencing concerns, thanks! That's useful. The spec still supports what I'm saying though, right? Even if the type is an HTTP URL, there is no requirement or guarantee that it leads to a real resource. The spec says that it's encouraged to do so, and no more, and NAME comment that "saying that these must be dereferenceable is potentially quite a big hurdle" seems to agree. Is that not correct? Assuming that's right then tooling can't use the URI as a helpful documentation link for devs, or anything similar. That's not valid because is not specified to be a URL of a resource at all. It's not designed for human or machine consumption, it's only guaranteed to be usable as a type id. I think being able to use these URIs would be great. There's good use cases, from generic HTTP clients that helpfully link to error documentation in exceptions to , where I would love to pull in error docs alongside error responses. To build these tools we need a URL that's guaranteed to go to docs, if present. If the documentation URL were instead in a link header with an HTML media type, similar to other standards (e.g. the documentation link for the ) then that would be possible. Using a link header would also better fit with HATEOAS, and would make error docs immediately visible to existing tooling that isn't aware of problem details. Imho, as a developer I would find this spec more useful if they were indeed decoupled, and the type wasn't necessarily a URI at all (meaning no duplication & possible inconsistency). Doing so would resolve all the feedback above, would make this standard would be easier to get started with, it'd support more cases like error types that share the same documentation URLs and support changing doc URLs, it'd avoid semantics like relative URIs that are not being implemented correctly, it would support more dereferencing use cases, and it would better match existing patterns in other specifications and in existing real-world APIs. I do see how this is subjective and debatable, but there's many benefits, and imho requiring type URIs like limits some valuable use cases. Going to leave this here for now, since I need to get some other work done! This is really interesting though, hope these points are helpful.
NAME The examples look good to me: … But afaict, none of those APIs implement RFC 7807 and thus aren't very relevant in this discussion. What's considered "common" is relative and up to the eye of the beholder. Using Universal Resource Identifiers as identifiers shouldn't be the esoteric, impenetrable mystery it's being described as, imho. Correct. Why not? I disagree. this design goal very clearly (emphasis mine): … What do you mean with "pull in"? Why not change it to "guaranteed to go to docs, if dereferenceable"? There's no one stopping anyone from doing exactly that. You avoid the duplication of resolved URIs if you use absolute URIs as your problem . It would also be a breaking change with existing software that actually implements the specification according to how it is written.
I think the problem is more with relative URIs. If I've been following the discussion correctly then this: Should be parsed as if the field was actually , because it's relative to the URL that actually requested the resource in the first place. And (almost) nobody actually does that - they all treat it as if the field was just instead. They're not, really. XML has been doing it for 20+ years with namespace URIs. There are probably examples that go back further too. As soon as you say "guaranteed" then you're putting a burden on developers. Especially when they plan to support dereferencing them at some future time, but not just yet. They will either ignore it, and thus not follow the spec correctly, or else it'll force them to use a different pattern for their URIs.
Exactly :+1:. Nowhere do any libraries I've seen even look at the resource URL, so they can never handle relative types correctly. The specification there states the goal of linking to a useful document and encourages that, but explicitly does not guarantee or mandate it. I think we agree it shouldn't, and that not all URIs will be links to usable documentation. AFAICT, it's totally valid to intentionally use an HTTP URI that leads to a 404. Meanwhile, no developer wants to be given a link to documentation and then hit a 404. If tools want to present URIs to developers as helpful links to human-readable documentation, they first need to know whether it is actually a link to a resource. The problem with "guaranteed to go to docs, if dereferenceable" as opposed to "if present" is that the former requires automatically dereferencing every to know if it's dereferenceable. The spec specifically discourages that, for the good reasons you've pointed out above, so we shouldn't design for that. An explicit link doesn't have this problem at all. Sorry, I don't mean to portray URIs as completely impenetrable, that's not fair. It seems true that the huge majority of existing APIs have existing error formats that don't use URIs for error codes though, and that many developers aren't very familiar with the nuances of URIs, e.g. URNs, tag URIs, etc. URIs are also clearly more complicated than plain strings, and all else being equal it would be good to make implementing this standard (and all standards!) as simple as possible. I really think existing widely used APIs are relevant to this standard (and all API standards!). Those APIs don't use this RFC today, but the standard only becomes useful if it's widely used by real clients and APIs. Popular APIs like Stripe/AWS/et al eventually supporting this is part of that, and adoption is easier for them if it fits their existing patterns (for example, they wouldn't need to change their existing error code documentation, or change logic that checks those codes). Adoption is similarly easier for clients and APIs responses are easier to immediately understand if the format fits their expectations, which are largely based on the common patterns they see in existing APIs. If we want the standard to be widely adopted, we have to care about existing API patterns (and I really want this standard to be widely adopted!) Ok, so as discussed, using URIs for does have some downsides, but we do have two concrete benefits that we've mentioned so far: It strongly encourages namespacing. It potentially links the type to a resource. Are there others I've missed? I think my position is that the first benefit is good, but IMHO outweighed by the downsides (and would still be an option for those who want it without requiring URIs) whilst the 2nd benefit isn't fully realized in the current draft (you can't automatically know whether it's a usable link or just an id) and would be better realized with link headers (more explicit, more standard, less coupled). Yep, even if we agree that this would be beneficial, there is definitely a question of compatibility with existing implementations. I think there's some good routes through here with minimal impact, and this is still a draft anyway. I don't think it makes much sense to do detailed analysis & planning for that though until there's some consensus on the kind of changes we'd like to make.
NAME There's absolutely no guarantee that can be given by anyone, anywhere, at any time, that any URI will resolve to anything at all. All URIs can lead to 404, no matter what their context and semantics are and no matter how many different avenues to provide links you give. Given enough time, most URIs end up pointing to a domain squatted by a shark. Is this of concern to RFC 7807bis? I believe it isn't. Scratch "guarantee" altogether. No guarantees can be given. Let's work from that premise and see where we go. The perception of impenetrable mystique built around URIs affects both how RFC 7807's is perceived as well as how hypermedia is approached (or rather, isn't) in the realm of APIs. Unlike you, though, I think that's ample reason to not give in to the perception, but instead, evangelize for more use of URIs both as identifiers as well as the target of hypermedia controls in an API. The fact that most HTTP APIs aren't RESTful by any stretch of the imagination doesn't make it right for a standardization organization such as IETF to cave in and succumb to the million flies doctrine. I'd say the right thing to do is the direct opposite and continue to normalize the use of URIs as well as hypermedia so APIs can become more, not less, RESTful over time. I think that's just a matter of familiarity. Use URIs enough and they become the opaque identifiers they are meant to be. A simple solution to this may perhaps be to override the base URI. Since  isn't an option and afaik no link relation exists, we need another way to establish a base URI, perhaps by registering the link relation. Another alternative is to add a slash to make the URI absolute: . Now you have a that will be considered equal no matter how you compare it against a given in a response from the same authority. As a reminder of how bad sad the status quo is, perhaps. True. As discussed in , there's an existing desire to reuse URIs across different APIs, something which is impossible with opaque strings since you have no idea whether coming from three different APIs means: It is currently impossible to let a current of air into the enclosed space specified in the request. The document specified does not exist in draft form and may be published or deleted. Military enrolment is currently not possible. Semantical ambiguities like these aren't insignificant and URIs solve them elegantly and efficiently. is a testament to how successful the use of URIs to identify things in an unambiguous, unique, and reusable way, really is. Please elaborate. RFC 7807bis is a draft, RFC 7807 isn't.
There's also the fact that not all URIs are resolvable for all clients. It's entirely possible that the URI resolves correctly for the server developer, but some client is behind some firewall that doesn't allow access to it. Or it might be temporarily down. Or a myriad of other reasons why a reasonable URI can't be resolved right now. That's still relative. If I understand things correctly, the path segment is now absolute but the schema/host/port/etc isn't specified so become relative to the original request. If you got that type from different APIs on different hosts then the resolved absolute URI is still different. It's perfectly possible with opaque strings. It's not possible with relative URIs iff the resulting value is first expanded to be an absolute URI - and thus might have a different value based on the scheme/hostname/port of the API being called. If the value was always an absolute URI or a relative URI that didn't get expanded then this problem goes away. Though at that point you've just got opaque strings that might or might not bear some resemblance to a URI.
Yes, that's why I wrote "from the same ". Not unless these strings are registered and clearly defined in a global registry. I agree that's just as useless as opaque, non-URI strings.
Ok, granted, you can't get a perfect guarantee. There is both a semantic and practical difference though between "here is a link that I intend you to dereference to find more information" and "here is a URI that is not intended to be dereferenced, it's just a type id". We currently allow both, intentionally, with no distinguishable difference until you dereference it. When looking for usable links to more information, any tooling is interested only in the former, where the URL is very likely to be useful (granted, not guaranteed). Meanwhile if you ever accidentally use the latter it's extremely likely to provide a bad user experience. It's very easy to differentiate these cases, and it would be useful, so we should. Unfortunately that's the same problem: client implementations do not take the authority into account either, they never use the base URL. I agree that they should, but right now it looks like most implementations of this specification handle both relative & absolute paths incorrectly, and only correctly use fully specified absolute URIs. I agree that URIs are excellent! I don't object to the use of URIs, I object to requiring that all APIs errors use URIs in all cases, as we do right now. There's lots of feedback (see above) that others feel similarly, and would like to use this spec without URIs. As an interesting supporting point: the WHATWG URL specification all references to URIs because "URI and IRI are just confusing". URIs are not well understood by many developers, and that will limit adoption of this spec. Right now, as in the blog post above, some users avoid using entirely because it's confusing and they don't want to create pages for every error type. This creates more semantic ambiguity than the status quo! Ok, one option would be: Make a freeform string where every response from the same API with that code represents the same type of error. Unspecified still defaults to . Just one constraint: if is an absolute URI, it must either be a URI already reserved for that purpose or a URI under the control of the API using it (e.g. HTTP/tag on your domain). This has no compatibility impact for existing APIs using absolute type URIs. Types in their existing responses are still valid and retain extremely similar rules for error type matching (technically there could be differences, e.g. # fragments in URL shouldn't be considered in URL comparisons, but I would be astonished if that is in use and working correctly for error handling in any API today). No compatibility impact for clients receiving existing responses that are absolute URIs or absolute paths, for similar reasons. Semantics change slightly for clients & APIs using path-relative URI types. Today these should be assumed to be distinct types per endpoint, and they would instead be treated as API-global. Helpfully, it appears that most implementations match this proposed behaviour today already, rather than the specified behaviour. In addition, impact of incompatibility is low: clients would incorrectly treat error types as distinct unrecognized errors, and would fail in slightly less granular ways. Clients who parse as a URI have potential compatibility issues parsing non-URI responses. This risk is low because: This doesn't affect or invalidate any existing client & API exchange that works today. It only affects clients newly making requests to APIs who start using some new URI-unparseable error type. URI syntax is very permissive, so most plain strings that would be used are also valid relative URIs, e.g works just fine (though, as mentioned, its semantics change slightly as it's currently a relative URI). It's very difficult to come up with examples of plausible error codes that would fail to parse as URIs. We could tighten the allowed characters if this is a concern. If a type is an absolute URI defined in a URI registry of common types or otherwise recognized by the client, the error SHOULD be treated as an instance of the globally registered error types (i.e. ) Fully compatible, and we retain the ability to share types across different services By putting into this URI registry, we retain the same semantics for that APIs are encouraged to use absolute URIs as types, for namespacing and type-sharing benefits, but this becomes optional. APIs who have documentation relevant to the error response should include a link header. I'd suggest we mint a new relation . This would pair very nicely with the existing . Service-doc provides general documentation for the resource, problem-doc provides documentation for the type of error returned. That resolves all the points above, with minimal backward compatibility impact. It still supports all the benefits that absolute URIs give us for those who want that, but also supports other cases too. Would that work for you? Are there specific compatibility concerns in here that would need further mitigation?
I've been working with XML for many years, where XML namespaces are URIs that almost never dereference to anything. In fact, there are normally specific mechanisms in XML tooling to know where the XSD for a given namespace is simply because the namespace URI doesn't dereference. And it works fine. People use it, and all is good. So tooling only being interested in dereferenceable links isn't strictly accurate. In terms of your proposal. My one concern with it is that I suspect many developers will opt for the choice of just using error codes instead of URIs, because they find it easier. That then means that you lose namespacing, you lose the ability for different APIs to share the same error types, and probably other things. There's also the minor concern that strictly speaking you can't distinguish a URI from an arbitrary string that happens to have the same format. Somebody might write a string that just happens to contain in the middle of it. Is that a URI? Or is it a coincidence? That's very much an edge case though and almost certainly can be ignored :) The impact on existing clients is also a concern, if it means that suddenly they can't understand errors that they could before. That's only an issue for clients that are correctly handling relative URIs though, and I don't know how many of those there are - if any.
True. I'm really talking about a specific subset of tooling, I should be more specific. I'm thinking about tooling that might format an error response for human consumption, like debuggers, manual clients like Postman & curl, loggers, and other error reporting tools. I think those are tools that could get a lot of value from this spec, and in many of these cases it's useful to know if the URL is documentation intended for human consumption. It's slightly more general unfortunately, since some absolute URIs only contain e.g. . If that's a concern, I think saying "error types must not contain : unless they're an absolute URI" would be a reasonable constraint, and would support most error codes you see in the real world. Explicitly specifying that would help parsers to quickly differentiate the two cases too. That is quite possible. It appears that there's also a group of people who currently avoid the spec altogether though, or use it suboptimally, because of the URI requirement. Standard formatting of error messages seems very valuable even without URIs. Personally I'm OK with this. Error types intended to be reused elsewhere can use URIs, and error types not intended for global reuse don't need URIs. The challenging case is when you want to reuse a URI defined by somebody else who didn't explicitly make it reusable. I'm OK with not supporting that, but I see how others might find this useful. Yep. I doubt it's used much though, and I suspect this change would actually increase the number of implementations that matched the spec when using relative URIs. I'd be really interested to know if anybody can find an example of a relative URI in production anywhere though.
But RFC 7807 does not state "here is a URI that is not intended to be dereferenced, it's just a type id". It states that should not be automatically dereferenced. Dereferencing based on a user's action, perhaps by clicking "view documentation" in a UI is perfectly fine and should probably be encouraged for documentation purposes in the specification. rfc7808bis should seek to clarify that. If the link doesn't resolve, the UI would have to recover from that failure somehow regardless of the semantics and guarantees that were given regarding the link that was dereferenced. "Sorry, no documentation for is available" is a fine error message for just as it is described by the specification as well as for a new URI that as such don't provide anything valuable doesn't already provide. Why would the user experience be bad? Please elaborate. Then they don't have the problem described, since they will just compare with across all responses, regardless of the context (base) URI. For clients that don't treat as a URI, in response A is just an opaque string, indiscernible from in response B, even though A and B may be from entirely different authorities altogether (although within the same API, I assume). I think you meant "URL" and not "URI" here, but regardless I agree with WHATWG in that both "URI" and "IRI" are confusing and don't add much to the more prevalent "URL". I'm not sure IETF is ready to replace its usage of "URI" to "URL" yet, though. That would probably require rfc3986bis of some sort. I agree URIs are not well understood. But I think that is a problem and believe the solution is not to cave in and stop using URIs, but to use even more URIs. ! Then let's invest in making it less confusing in rfc7807bis! They don't have to. Let's be more explicit about that. More examples could perhaps help. Sorry, no. I'll just +1 NAME criticism here. I don't think this is going to work. In hindsight, it may have been better if non-URI values were interpreted not as relative URIs, but as implicit URNs or something similar. But that train sailed with a boat on water under the bridge more than 5 years ago. Yes, your suggestion is going to break clients with the following expectations: URIs that point to external documentation. Non-absolute URIs are relative to the context. Isn't it possible for these tools to only present documentation upon a user's explicit action? If is dereferenceable, the content is intended for human consumption. Perhaps we could survey these people on the reason they're not using RFC 7807 instead of just speculating? I believe your suspicion may be correct. I would love to see the result of a survey of existing implementations before concluding, but I'm currently +0 to make the compromise of making non-URI implicit URNs or some other similar solution that doesn't convert them into context-relative HTTP(S) URIs.
To expand on the "making non-URI implicit URNs", this sort of implicit expansion has precedent in 's definition of : >The value of "rel" MUST be a string that is non-empty and matches either the "isegment-nz-nc" or the "IRI" production in ]. Note that use of a relative reference other than a simple name is not allowed. If a name is given, implementations MUST consider the link relation type equivalent to the same name registered within the IANA Registry of Link Relations (), and thus to the IRI that would be obtained by appending the value of the rel attribute to the string "". In , values are either required to be registered in IANA's Link Relation Registry, or in the case of Extension Relation Types, full URIs. RFC 7807's deviation from these two mechanisms in making relative to the context is perhaps the source of the greatest issue here. I've come to agree that should be comparable across problem documents disregard of their request context.
Hey NAME - that's interesting, but it's backwards-incompatible, so we'd need to use a new media type. Is that worth it (considering the resulting confusion, etc.)?
Sorry for being imprecise. What I meant was that I agree with (part of) the problem description. I'm +0 on actually doing anything about it. If enough weight is put behind a new media type to break with the current implementations of , then I would not oppose it.
The obvious concern with a new media type is that implementers will either need to migrate completely over to it, or else end up supporting two different ways of representing problems. That feels at odds with what - to me - is one of the major benefits of RFC-7807 in the first place, that there is one standard way to do this and you'd need a good reason to do something different.
the discussion around using URIs as identifiers has been had what feels like a million times. everybody knows the implications. it's a design trade-off. given that there is no clear "winner" i think not breaking the existing media type should make it a big preference to stick with what we have. i am more than willing to make proposals how to improve the language so that people reading the spec get a bit more context and assistance. but as we all know, specs are not read as much as one might wish, so we'll still see broken implementations out there. that's just life.
Whilst it would still be technically incompatible, I think the practical outcome from would be that: The incompatibility only affects fully relative URIs (e.g. ). Both absolute URIs and absolute paths would retain effectively identical semantics to the current spec. That incompatible case is not used or discussed in the wild anywhere that I've ever seen (counter examples very welcome!) In generic implementations, the incompatible case appears to be incorrectly implemented everywhere, with every implementation I've seen already matching the proposed rather than specified behaviour for this case. It seems likely that this breaking change would dramatically increase the number of implementations correctly implementing the specification today. Does that affect the calculus on breaking changes here? (I do agree that NAME proposal to make relative error types global by default has much larger compatibility implications, unfortunately, and that minting a new media type has repercussions that make this unlikely to be worthwhile in either case)
Not quite. Absolute URIs retain identical semantics. Absolute paths only retain identical semantics if they are from the same scheme and authority. If they come from different authorities then the resolved URI from those absolute paths is different, and thus the value to use under the current spec is different. However, as you say, nobody does that. At least, nobody that I've ever seen. I don't know how we'd find out if introducing a breaking change is actually going to break things in any real code, but it seems to me that this proposed change is the cleanest route and that the risk of breaking things is mitigated by the fact that (almost) everybody does it wrong now anyway. The other option would be to introduce not a new media type, but a new parameter to the existing media type. So it becomes . Anyone who doesn't specify a value for would then be assumed to be using the most recent version of the spec, which is what we're discussing here. If they explicitly want to retain the old behaviour then they would specify . (That would also open the door for further future changes that introduce a as well.) I will say, I'm not hugely thrilled by that idea. I prefer trying to keep things simple and not need to do any versioning like that. But it is an option.
In the proposed version, both relative & absolute paths would be considered as scoped to the API (i.e. the scheme & authority). So should be treated as same type of error everywhere in the API (unlike today) and as distinct types if returned from different APIs (same as today). doesn't change though: it should be treated as the same type everywhere in the same API (the same as today) and as distinct types if returned by different APIs (the same as today). Does that not match today's semantics? Maybe I'm missing something, do you have an example where the behaviour changes?
So it seems like we have some agreement that we don't want to introduce a new mime type, and as a result we shouldn't change the nature of in a backwards-incompatible fashion. Proposal: we should resolve this issue by focusing on making the spec communicate more clearly about how to use URIs successfully in , possibly adding new fields, etc. in separate issues. Once we do that, we should close this issue, but label it so that if for some reason we find a compelling enough reason to mint a new mime type, we remember to reconsider.
Personally I'd still prefer the technically-incompatible-but-probably-more-compatible proposal with no mime type change at all, but I can understand if that's not an acceptable risk. If we're talking about guaranteed-safe changes we can make, the things I'd personally find useful are: Making a clear & simple recommendation in the spec for users who have a simple error code and who don't want to link the error type to a documentation page. E.g. they should use tags, or URNs, or absolute paths, or something else. Discouraging fully relative paths, since they're very counter-intuitive, most/all implementations handle them wrong, and we may want to change their semantics in a future breaking change. Providing some way for clients to know if a type URL is designed to be dereferenced as a link to documentation, or if it's simply acting as an identifier. I'll file new issues for those, and we can continue discussion on them independently there. Happy for this issue to be tagged and left for a future breaking change in the meantime if that's all we can do for now.
See PR . Thoughts?
Am merging , which will close this. If anyone has further input, please open a new issue or comment.
I've added a couple of quick thoughts on ways this could go slightly further, but I think this is already a great improvement that would

A problem details object can have the following members:  <ins> 3.2. The "type" member is a JSON string containing a URI reference RFC3986 that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML HTML5).  When this member is not present, its value is assumed to be "about:blank". When "type" contains a relative URI, it is resolved relative to the document's base URI, as per RFC3986, Section 5.  However, using relative URIs can cause confusion, and they might not be handled correctly by all implementations.  For example, if the two resources "https://api.example.org/foo/bar/123" and "https://api.example.org/ widget/456" both respond with a "type" equal to the relative URI reference "example-problem", when resolved they will identify different resources ("https://api.example.org/foo/bar/example- problem" and "https://api.example.org/widget/example-problem" respectively).  As a result, it is RECOMMENDED that absolute URIs be used in "type" when possible, and that when relative URIs are used, they include the full path (e.g., "/types/123"). Consumers MUST use the "type" URI (after resolution, if necessary) as the primary identifier for the problem type.  Consumers SHOULD NOT automatically dereference the type URI. 3.3. The "title" member is a JSON string containing a short, human- readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see I-D.ietf-httpbis-semantics, Section 12.1). The "title" string is advisory and included only for users who are not aware of the semantics of the URI and do not have the ability to discover them (e.g., offline log analysis). 3.4. The "status" member is a JSON number indicating the HTTP status code (I-D.ietf-httpbis-semantics, Section 15) generated by the origin server for this occurrence of the problem. </ins> The "status" member, if present, is only advisory; it conveys the HTTP status code used for the convenience of the consumer. persist without HTTP information.  Generic HTTP software will still use the HTTP status code. <ins> 3.5. The "detail" member is a JSON string containing a human-readable explanation specific to this occurrence of the problem. </ins> The "detail" member, if present, ought to focus on helping the client correct the problem, rather than giving debugging information. extensions are more suitable and less error-prone ways to obtain such information.  <ins> 3.6. The "instance" member is a JSON string containing a URI reference that identifies the specific occurrence of the problem.  It may or may not yield further information if dereferenced. When "instance" contains a relative URI, it is resolved relative to the document's base URI, as per RFC3986, Section 5.  However, using relative URIs can cause confusion, and they might not be handled correctly by all implementations.  For example, if the two resources "https://api.example.org/foo/bar/123" and "https://api.example.org/ widget/456" both respond with an "instance" equal to the relative URI reference "example-instance", when resolved they will identify different resources ("https://api.example.org/foo/bar/example- instance" and "https://api.example.org/widget/example-instance" respectively).  As a result, it is RECOMMENDED that absolute URIs be used in "instance" when possible, and that when relative URIs are used, they include the full path (e.g., "/instances/123"). 3.7. </ins> Problem type definitions MAY extend the problem details object with additional members.


4.2. <del> This specification reserves the use of one URI as a problem type: </del>  The "about:blank" URI RFC6694, when used as a problem type, indicates that the problem has no additional semantics beyond that of the HTTP Please update the "application/problem+json" and "application/ problem+xml" registrations in the Internet media types registry RFC6838. to refer to this document.

Note that the recommendation regarding a URI prefix for registered values is subject to other discussions.
my reading of RFC 7807 is that the vanilla status codes do not need types and this is where about:blank is explicitly recommended (if somebody does not want to simply omit the type URI, which also is allowed). i think this is how the RFC does it and i don't think we even have the option to change this and to now recommend specific type URIs for vanilla problem reports.
(I'm not sure if this is the correct place to propose this, so apologies if not!) As RFC-7807 gains wider-spread adoption, it is becoming the case that more and more APIs are returning effectively the same problems with different values for the fields. This makes it difficult to work across different APIs, because you need to understand that different problems from those APIs actually mean the same thing. Common examples that you might expect to see include: Resource not found Authentication failure Optimistic lock failure (e.g. the header on a request has the wrong value) Request validation failure It seems that it would be useful to have a repository of these common problem types that can then be reused across APIs, so that ideally these common situations can be handled in the exact same way on the client. Effectively the same idea as the standard list of , whereby all clients that see a link relation of, for example, or know what they mean regardless of the API that produced them.
Unlike relation type name ( or type` is a URI in 7807. Is there any other example of a repository of entities where each entity is uniquely addressable? Also, I am working on API for such a repository URL (When you read, replace "Error Type" with "Problem Type" and "Error Catalog" with "Problem Type Repository"). I would like to submit it here to evolve it if there is interest.
My concern here, and why I raised this ticket, is less to do with APIs using the same value for different meanings, and instead to do with APIs using different values for the same meaning. Mostly it makes API design that bit easier if there is a well known value to use for what you're trying to indicate.
There are a couple of ways to go here: Create an IANA registry of problem types, much as for link relations. Create a publicly-coordinated informal repository (eg, in a wiki). Because types are required to be URIs, avoiding conflicts (one of the main reasons to use a registry) isn't relevant; it would be more to aid discovery. If we wanted some sort of quality filter on it, we'd probably use an IANA registry, and would need a process around that (e.g., expert review, IETF review; see ). Note that 7087 allows relative URIs in the field, we couldn't use bare tokens like link relations do. However, if folks wanted "neutral" URIs that didn't reflect a particular vendor, we could easily mint URIs in a common name space like or or something else. P.S. Resource Not Found and Authentication Failure are already HTTP status codes -- 404 and 401, respectively (unless you mean non-HTTP auth in the latter case).
These are already HTTP status codes, but it's not unreasonable for APIs to want to always return a Problem response for any error. Sometimes it's easier to develop the server code that way (e.g. in Rust it's very verbose to have many different response types.) Sometimes it's easier to allow clients to always assume an response. Sometimes it's just that people like consistency. And actually the only real downside seems to be that the response payload is non-zero in size Given that though, it means that people start to mint URIs for problem types that directly correspond to HTTP status codes. And, odds are, different people do it differently. That's a key example where some standard values would just make that a little bit easier. For example, I've started using values like in these cases - it doesn't actually tell you anything more than the HTTP status code, but it means that the response body is always in a consistent format which just makes life that little bit easier in some cases. (I did consider a link to the appropriate section of RFC-7232, but that seemed a bit more awkward given that it would need a fragment in the URI)
The RFC recommends that be used in this situation. We intentionally did not have per-status-code values, because that would encourage developers to ignore the real status code, and because duplicating values at different layers is a vector for bugs and security issues.
Ah - I'd totally missed that paragraph! That does make a lot of sense, especially when coupled with the absence of the "type" parameter mapping on to "about:blank". :)
For "standard" problem types, would folks be willing to stomach the form? That's likely the most permanent, easy way to do it. Using is also possible, as would be . Some might complain that they (especially the former) are rooted in DNS, and therefore might not be stable over a long time scale. Another option would be minting our own URI scheme, to make something like . That might make some of the URN folks unhappy, though; would have to try to find out.
I think we need to before we can decide on the format.
I guess the form we go for depends on some other things. If we decide (per as NAME says) that the value should be a URI, and that it should resolve to documentation, then something like might be better. But then, as you say, that means that URL has to remain stable for the foreseeable future. Personally speaking, I'm fine with the idea - I currently always use for mine anyway - but it does mean that they are definitely not resolvable. I'm less keen on the idea of a new scheme. It is obvious what's happening, but it does start to look like all problems must be in that scheme, which then potentially defeats the point of in the first place. Also, (and I might be missing things here) it seems that the only real benefit of over is in the length of the string, which isn't a huge deal - it's a saving of 17 characters.
In the meeting, folks seemed to pretty strongly lean towards an IANA registry with some bar to entry (TBD).
See for a proposal.
thanks for , NAME i like it, but my concern is a bit that if we have a registry, wouldn't it make more sense to suggest using a URN scheme or a URN pattern ( was proposed above) for registered type? the registry specifically is there for discovery, so we don't have to use HTTP URIs which create the risk of tooling accessing those URIs and creating unnecessary load. my personal preference would be to go the URN way (scheme or pattern) and maybe add a section on discovery, which would then point out these alternatives: if you use custom types, you have to think about discovery. if you think about registering types, then discovery is taken care of by the registry, so using a non-dereferencable URI may be the better option to choose.
NAME see discussion in .
thanks for the pointer, i forgot about that one... i still think that using a URN is cleaner and more google friendly (seeing that automated dereferencing is not the goal here), but of course both options technically work. maybe this would be something useful to present as a choice to be made in the next meeting.
just in case anybody is interested in a general discussion of why and how to use registries, here's something i wrote a while ago that discusses various aspects of the general pattern: URL
Discussed in 111: no strong feelings about URI scheme; a bit of preference for urn.
I'm going to go ahead and merge as is; we can address the URI scheme part as our thinking on that develops.
i like it, but i am wondering if proposing a URI that points at the IANA registry isn't potentially a risky thing to do (in terms of driving traffic to that URI). i personally like the idea of a dedicated URN scheme better, as we will now have the registry to aid with discovery.

4.2.  <ins> This specification defines the HTTP Problem Type registry for common, widely-used problem type URIs, to promote reuse. Registration requests are reviewed and approved by a Designated Expert, as per RFC8126, Section 4.5.  A specification document is appreciated, but not required. When evaluating requests the Expert(s) should consider community feedback, how well-defined the problem type is, and this specification's requirements.  Vendor-specific, application-specific, and deployment-specific values are not registrable. Registrations MAY use the prefix "https://iana.org/assignments/http- problem-types#", and are encouraged to do so when a stable, neutral URI is desirable. Registration requests should use the following template: Type URI: [a URI for the problem type] Title: [a short description of the problem type] Recommended HTTP status code: [what status code is most appropriate to use with the type] Reference: [to a specification defining the type] See the registry at https://iana.org/assignments/http-problem-types [1] for details on where to send registration requests. 4.2.1. This specification registers one Problem Type, "about:blank". Type URI: about:blank Title: See HTTP Status Code Recommended HTTP status code: N/A Reference: [this document] </ins> The "about:blank" URI RFC6694, when used as a problem type, indicates that the problem has no additional semantics beyond that of the HTTP Please update the "application/problem+json" and "application/ problem+xml" registrations in the Internet media types registry RFC6838. to refer to this document. <ins> Please create the HTTP Problem Types Registry, as specified in registry, and populate it with "about:blank" as per blank. 7.  References 7.1.  URIs [1] https://iana.org/assignments/http-problem-types </ins>