<h3 dir="auto">Preflight Checklist</h3>

<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have read the <a href="https://github.com/electron/electron/blob/master/CONTRIBUTING.md">Contributing Guidelines</a> for this project.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow the <a href="https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md">Code of Conduct</a> that this project adheres to.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the issue tracker for a feature request that matches the one I want to file, without success.</li>
</ul>
<h3 dir="auto">Problem Description</h3>

<p dir="auto">The product I'm developing now implements a custom error for gRPC to make the error handling. Then, by passing the additional information for the errors made by gRPC to the renderer, I am trying to do a flexible display of error messages with the renderer.</p>
<p dir="auto">For example, I am trying to use custom errors in the following situations</p>
<ul dir="auto">
<li>display the ID of data that failed to be received</li>
<li>Handle custom error codes contracted to the gRPC server</li>
</ul>
<p dir="auto">However, <a href="https://github.com/electron/electron/blob/659e79fc08c6ffc2f7506dd1358918d97d240147/lib/renderer/api/ipc-renderer.ts#L24-L30">ipcRenderer.invoke</a> does not allow to receive custom error generated on main process because this function make simple Error() instance with error message.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="ipcRenderer.invoke = async function (channel, ...args) {
  const { error, result } = await ipc.invoke(internal, channel, args);
  if (error) {
    throw new Error(`Error invoking remote method '${channel}': ${error}`);
  }
  return result;
};"><pre class="notranslate"><span class="pl-s1">ipcRenderer</span><span class="pl-kos">.</span><span class="pl-en">invoke</span> <span class="pl-c1">=</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">channel</span><span class="pl-kos">,</span> ...<span class="pl-s1">args</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-kos">{</span> error<span class="pl-kos">,</span> result <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">ipc</span><span class="pl-kos">.</span><span class="pl-en">invoke</span><span class="pl-kos">(</span><span class="pl-s1">internal</span><span class="pl-kos">,</span> <span class="pl-s1">channel</span><span class="pl-kos">,</span> <span class="pl-s1">args</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Error</span><span class="pl-kos">(</span><span class="pl-s">`Error invoking remote method '<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">channel</span><span class="pl-kos">}</span></span>': <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">error</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-k">return</span> <span class="pl-s1">result</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">Proposed Solution</h3>

<p dir="auto">I don't fully understand the <a href="https://github.com/electron/electron/blob/72a089262e31054eabd342294ccdc4c414425c99/shell/renderer/api/electron_api_ipc_renderer.cc#L105-L129">ipc.invoke process described in cpp</a>. If ipc.invoke can return a error thrown by the main process directly, I think the following changes will satisfy my wishes.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="ipcRenderer.invoke = async function (channel, ...args) {
  const { error, result } = await ipc.invoke(internal, channel, args);
  if (error) {
    throw error;
  }
  return result;
};"><pre class="notranslate"><span class="pl-s1">ipcRenderer</span><span class="pl-kos">.</span><span class="pl-en">invoke</span> <span class="pl-c1">=</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">channel</span><span class="pl-kos">,</span> ...<span class="pl-s1">args</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-kos">{</span> error<span class="pl-kos">,</span> result <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">ipc</span><span class="pl-kos">.</span><span class="pl-en">invoke</span><span class="pl-kos">(</span><span class="pl-s1">internal</span><span class="pl-kos">,</span> <span class="pl-s1">channel</span><span class="pl-kos">,</span> <span class="pl-s1">args</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">throw</span> <span class="pl-s1">error</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-k">return</span> <span class="pl-s1">result</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">However, the information on the channel drops off. I'd like to come up with a solution here when how to handle custom error policy is decieded.</p>
<h3 dir="auto">Alternatives Considered</h3>

<h3 dir="auto">Additional Information</h3>

<p dir="auto">If it's the current implementation in relation to the cpp part of the implementation, please let me know. I'm glad to see it. I'm also glad that this custom error policy is being used as an anti If it's a pattern, I'd be happy to point that out as well.</p>
<h3 dir="auto">Preflight Checklist</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have read the <a href="https://github.com/electron/electron/blob/main/CONTRIBUTING.md">Contributing Guidelines</a> for this project.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow the <a href="https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md">Code of Conduct</a> that this project adheres to.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://www.github.com/electron/electron/issues">issue tracker</a> for a feature request that matches the one I want to file, without success.</li>
</ul>
<h3 dir="auto">Problem Description</h3>
<p dir="auto">The Electron <code class="notranslate">net</code> module (and other associated APIs, types, etc.) is supposed to be similar to Node's <code class="notranslate">http</code> and <code class="notranslate">https</code> modules. At this point in time however, Electron's <code class="notranslate">IncomingMessage</code> does not expose <code class="notranslate">rawHeaders</code>.</p>
<h3 dir="auto">Proposed Solution</h3>
<p dir="auto">Expose a <code class="notranslate">rawHeaders</code> on <code class="notranslate">IncomingMessage</code>. The return value should be similar to that as in the <code class="notranslate">http</code> module:</p>
<blockquote>
<p dir="auto">The raw request/response headers list exactly as they were received.</p>
<p dir="auto">The keys and values are in the same list. It is not a list of tuples. So, the even-numbered offsets are key values, and the odd-numbered offsets are the associated values.</p>
<p dir="auto">Header names are not lowercased, and duplicates are not merged.</p>
</blockquote>
<p dir="auto"><a href="https://nodejs.org/api/http.html#messagerawheaders" rel="nofollow">https://nodejs.org/api/http.html#messagerawheaders</a></p>
<h3 dir="auto">Alternatives Considered</h3>
<p dir="auto">Don't use Electron <code class="notranslate">net</code> module. I don't want to do this because of the greater functionalities of <code class="notranslate">net</code> vs the Node <code class="notranslate">http</code> and <code class="notranslate">https</code> modules.</p>
<h3 dir="auto">Additional Information</h3>
<p dir="auto">I am more than happy to implement this myself!</p>