Repository: netlify/zip-it-and-ship-it
Pull request #616 (2021-08-19 16:53:59)

feat: improve custom error tagging
**- Summary**

This PR tags errors resulting from compiling Go and Rust binaries as custom `functionsBundling` errors. A `runtime` is included in the error metadata, indicating the runtime where the error occurred. This property has been added to the JavaScript runtime too.

**- Test plan**

New tests added.

**- A picture of a cute animal (not mandatory but encouraged)**

![wall-murals-cute-koala-bear-sitting-on-tree jpg](https://user-images.githubusercontent.com/4162329/130110775-a4ed6b3f-6bad-4762-94d7-fc1d86e61d19.jpg)


github-actions[bot]: ## ⏱ Benchmark results

*Comparing with 4bec0a78760c82c52dd8b352abfd286306dacd80*

### largeDepsEsbuild: 14s
 ⬆️ **20.69% increase** vs. 4bec0a78760c82c52dd8b352abfd286306dacd80
```
^  13.8s                                                           13.9s                            14s   
│   ┌──┐   13.2s                                                    ┌──┐                            ┌──┐  
│   |  |    ┌──┐   12.6s           12.9s   12.3s           12.7s    |  |                            |▒▒|  
│   |  |    |  |    ┌──┐            ┌──┐    ┌──┐   12.1s    ┌──┐    |  |                            |▒▒|  
│ ──┼──┼────┼──┼────┼──┼────────────┼──┼────┼──┼────┌──┐────┼──┼────┼──┼───────────10.9s────────────|▒▒|──
│   |  |    |  |    |  |   10.5s    |  |    |  |    |  |    |  |    |  |   10.6s    ┌──┐            |▒▒|  
│   |  |    |  |    |  |    ┌──┐    |  |    |  |    |  |    |  |    |  |    ┌──┐    |  |    9.8s    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    ┌──┐    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
└───┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴──>
    T-12    T-11    T-10    T-9     T-8     T-7     T-6     T-5     T-4     T-3     T-2     T-1      T    
```
<details>
<summary>Legend</summary>

- T-30 (4bec0a78760c82c52dd8b352abfd286306dacd80): 11.1s
- T-29 (ccea887d6ce4d32a05319ea04bbdeb8fd7ac8073): 13.3s
- T-28 (d9c033420961859bd13239888f23396e6b02da45): 13.2s
- T-27 (58a459ea75a804c4c39002135cb5cbc9ff4bb677): 10.8s
- T-26 (0b084549ee3eb5c4dae9477d33ff10be8a533084): 11.7s
- T-25 (56f4d4a39cbdee23a5856037430ab627ce37ab22): 11.1s
- T-24 (7b77c5668a7ad785310d7c46010c2863935aaa9a): 13.3s
- T-23 (4a5a4922e0b8793c8b01af6aa55915ba518bc9bf): 11.6s
- T-22 (38f4d4753a7205b3ec242440b3d2a1bbd866131a): 10.2s
- T-21 (f41a7a28b9b049ade7b656b0dc79deb4f45c829e): 11.6s
- T-20 (65c4b941e2866aab49c77cb55504ddad4bdb50a2): 12.9s
- T-19 (e6490d61a256a27c70f3b602ec37e648d415b442): 10.9s
- T-18 (15787efd3bfac84e0036e96082d071afa67c42c5): 11.3s
- T-17 (1ce8157a7351adbc6c6c751ddc8499e9080536b8): 12.9s
- T-16 (96c833514c1b10081dee2a1c236e05186c2ebe01): 13.2s
- T-15 (5d48d64bea0d963efa9dbe64925baef24002a9a4): 12.4s
- T-14 (bd7206ea53810a73ea9938f4e34e2826a142ae2d): 14.3s
- T-13 (69fdb7b0f312a6e007e6cedd6a40494772756eef): 11.4s
- T-12 (57a644f24c7bfd2c0ab1e19360465a3301157162): 13.8s
- T-11 (a9a9e610e1324bbcbee604561605dd12c8a7c4c8): 13.2s
- T-10 (8e299a25c7449b440f7a07849d73b8f184a3245c): 12.6s
- T-9 (cebf521a0a5e42ee0244108aa86367f74524f1be): 10.5s
- T-8 (b789589e534a4cc26c6a56636039b9a22f07a2e3): 12.9s
- T-7 (2e25a52b4d23522c64a01c78f7dba16291a085cf): 12.3s
- T-6 (fec9333941c4b8d0a6a648fd755ddecca07fc892): 12.1s
- T-5 (bd61ad00330f73d247dac787734abc9efeaba4b1): 12.7s
- T-4 (9c3d239efb5f53d53ada4c2d92db6f48b7401096): 13.9s
- T-3 (d790873c4cfb82de3f9d5cc64c2ecb45f4c4112f): 10.6s
- T-2 (c18abffd799ee05a0336a34fffd9a1d48e71c550): 10.9s
- T-1 (a0b35e4de9ee40eb9eed4fdd85a16796983fe154): 9.8s
- **T (current commit): 14s**</details>
### largeDepsZisi: 1m 13.3s
 ⬆️ **14.50% increase** vs. 4bec0a78760c82c52dd8b352abfd286306dacd80
```
^                                                                 1m 17.1s                                
│                                                                   ┌──┐                          1m 13.3s
│         1m 9.5s                 1m 8.3s                 1m 7.9s   |  |                            ┌──┐  
│ 1m 6.5s   ┌──┐  1m 3.8s           ┌──┐          1m 4.1s   ┌──┐    |  |                            |▒▒|  
│ ──┌──┐────┼──┼────┌──┐────────────┼──┼──1m 3.4s───┌──┐────┼──┼────┼──┼────────────────────────────|▒▒|──
│   |  |    |  |    |  |            |  |    ┌──┐    |  |    |  |    |  |           58.4s            |▒▒|  
│   |  |    |  |    |  |            |  |    |  |    |  |    |  |    |  |   54.3s    ┌──┐            |▒▒|  
│   |  |    |  |    |  |   51.2s    |  |    |  |    |  |    |  |    |  |    ┌──┐    |  |   51.8s    |▒▒|  
│   |  |    |  |    |  |    ┌──┐    |  |    |  |    |  |    |  |    |  |    |  |    |  |    ┌──┐    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
└───┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴──>
    T-12    T-11    T-10    T-9     T-8     T-7     T-6     T-5     T-4     T-3     T-2     T-1      T    
```
<details>
<summary>Legend</summary>

- T-30 (4bec0a78760c82c52dd8b352abfd286306dacd80): 1m 2.7s
- T-29 (ccea887d6ce4d32a05319ea04bbdeb8fd7ac8073): 1m 12.5s
- T-28 (d9c033420961859bd13239888f23396e6b02da45): 1m 11.3s
- T-27 (58a459ea75a804c4c39002135cb5cbc9ff4bb677): 59s
- T-26 (0b084549ee3eb5c4dae9477d33ff10be8a533084): 1m 3s
- T-25 (56f4d4a39cbdee23a5856037430ab627ce37ab22): 58.2s
- T-24 (7b77c5668a7ad785310d7c46010c2863935aaa9a): 1m 14s
- T-23 (4a5a4922e0b8793c8b01af6aa55915ba518bc9bf): 1m 6.9s
- T-22 (38f4d4753a7205b3ec242440b3d2a1bbd866131a): 59.9s
- T-21 (f41a7a28b9b049ade7b656b0dc79deb4f45c829e): 1m 5.4s
- T-20 (65c4b941e2866aab49c77cb55504ddad4bdb50a2): 1m 15s
- T-19 (e6490d61a256a27c70f3b602ec37e648d415b442): 59s
- T-18 (15787efd3bfac84e0036e96082d071afa67c42c5): 55.9s
- T-17 (1ce8157a7351adbc6c6c751ddc8499e9080536b8): 1m 2.9s
- T-16 (96c833514c1b10081dee2a1c236e05186c2ebe01): 1m 3.6s
- T-15 (5d48d64bea0d963efa9dbe64925baef24002a9a4): 1m 2.1s
- T-14 (bd7206ea53810a73ea9938f4e34e2826a142ae2d): 1m 11.7s
- T-13 (69fdb7b0f312a6e007e6cedd6a40494772756eef): 54.7s
- T-12 (57a644f24c7bfd2c0ab1e19360465a3301157162): 1m 6.5s
- T-11 (a9a9e610e1324bbcbee604561605dd12c8a7c4c8): 1m 9.5s
- T-10 (8e299a25c7449b440f7a07849d73b8f184a3245c): 1m 3.8s
- T-9 (cebf521a0a5e42ee0244108aa86367f74524f1be): 51.2s
- T-8 (b789589e534a4cc26c6a56636039b9a22f07a2e3): 1m 8.3s
- T-7 (2e25a52b4d23522c64a01c78f7dba16291a085cf): 1m 3.4s
- T-6 (fec9333941c4b8d0a6a648fd755ddecca07fc892): 1m 4.1s
- T-5 (bd61ad00330f73d247dac787734abc9efeaba4b1): 1m 7.9s
- T-4 (9c3d239efb5f53d53ada4c2d92db6f48b7401096): 1m 17.1s
- T-3 (d790873c4cfb82de3f9d5cc64c2ecb45f4c4112f): 54.3s
- T-2 (c18abffd799ee05a0336a34fffd9a1d48e71c550): 58.4s
- T-1 (a0b35e4de9ee40eb9eed4fdd85a16796983fe154): 51.8s
- **T (current commit): 1m 13.3s**</details>
<!--delta:benchmark@{}-->

Patch:
diff --git a/src/runtimes/go/builder.js b/src/runtimes/go/builder.js
index f76dc9c..dc1d6ef 100644
--- a/src/runtimes/go/builder.js
+++ b/src/runtimes/go/builder.js
@@ -1,5 +1,6 @@
 const { basename } = require('path')
 
+const { RUNTIME_GO } = require('../../utils/consts')
 const { lstat } = require('../../utils/fs')
 const { runCommand } = require('../../utils/shell')
 
@@ -15,6 +16,8 @@ const build = async ({ destPath, mainFile, srcDir }) => {
       },
     })
   } catch (error) {
+    error.customErrorInfo = { type: 'functionsBundling', location: { functionName, runtime: RUNTIME_GO } }
+
     console.error(`Could not compile Go function ${functionName}:\n`)
 
     throw error
diff --git a/src/runtimes/node/bundler.js b/src/runtimes/node/bundler.js
index 3cb58fa..a686f82 100644
--- a/src/runtimes/node/bundler.js
+++ b/src/runtimes/node/bundler.js
@@ -3,6 +3,7 @@ const { basename, dirname, extname, resolve, join } = require('path')
 const esbuild = require('@netlify/esbuild')
 const { tmpName } = require('tmp-promise')
 
+const { RUNTIME_JS } = require('../../utils/consts')
 const { getPathWithExtension, safeUnlink } = require('../../utils/fs')
 
 const { getBundlerTarget } = require('./bundler_target')
@@ -105,7 +106,7 @@ const bundleJsFile = async function ({
       warnings,
     }
   } catch (error) {
-    error.customErrorInfo = { type: 'functionsBundling', location: { functionName: name } }
+    error.customErrorInfo = { type: 'functionsBundling', location: { functionName: name, runtime: RUNTIME_JS } }
 
     throw error
   }
diff --git a/src/runtimes/rust/builder.js b/src/runtimes/rust/builder.js
index b199e4f..7c349ed 100644
--- a/src/runtimes/rust/builder.js
+++ b/src/runtimes/rust/builder.js
@@ -8,38 +8,27 @@ const makeDir = require('make-dir')
 const tmp = require('tmp-promise')
 const toml = require('toml')
 
+const { RUNTIME_RUST } = require('../../utils/consts')
 const { lstat } = require('../../utils/fs')
 const { runCommand } = require('../../utils/shell')
 
 const { BUILD_TARGET, MANIFEST_NAME } = require('./constants')
 
 const build = async ({ config, name, srcDir }) => {
-  await installBuildTarget()
-
-  const targetDirectory = await getTargetDirectory({ config, name })
   const functionName = basename(srcDir)
 
   try {
-    await runCommand('cargo', ['build', '--target', BUILD_TARGET, '--release'], {
-      cwd: srcDir,
-      env: {
-        CARGO_TARGET_DIR: targetDirectory,
-      },
-    })
+    await installBuildTarget()
   } catch (error) {
-    const hasToolchain = await checkRustToolchain()
-
-    if (!hasToolchain) {
-      throw new Error(
-        'There is no Rust toolchain installed. Visit https://ntl.fyi/missing-rust-toolchain for more information.',
-      )
-    }
-
-    console.error(`Could not compile Rust function ${functionName}:\n`)
+    error.customErrorInfo = { type: 'functionsBundling', location: { functionName, runtime: RUNTIME_RUST } }
 
     throw error
   }
 
+  const targetDirectory = await getTargetDirectory({ config, name })
+
+  await cargoBuild({ functionName, srcDir, targetDirectory })
+
   // By default, the binary will have the same name as the crate and there's no
   // way to override it (https://github.com/rust-lang/cargo/issues/1706). We
   // must extract the crate name from the manifest and use it to form the path
@@ -55,6 +44,30 @@ const build = async ({ config, name, srcDir }) => {
   }
 }
 
+const cargoBuild = async ({ functionName, srcDir, targetDirectory }) => {
+  try {
+    await runCommand('cargo', ['build', '--target', BUILD_TARGET, '--release'], {
+      cwd: srcDir,
+      env: {
+        CARGO_TARGET_DIR: targetDirectory,
+      },
+    })
+  } catch (error) {
+    const hasToolchain = await checkRustToolchain()
+
+    if (hasToolchain) {
+      console.error(`Could not compile Rust function ${functionName}:\n`)
+    } else {
+      error.message =
+        'There is no Rust toolchain installed. Visit https://ntl.fyi/missing-rust-toolchain for more information.'
+    }
+
+    error.customErrorInfo = { type: 'functionsBundling', location: { functionName, runtime: RUNTIME_RUST } }
+
+    throw error
+  }
+}
+
 const checkRustToolchain = async () => {
   try {
     await runCommand('cargo', ['-V'])


Test patch:
diff --git a/tests/fixtures/go-source/go-func-2/go-func-2.go b/tests/fixtures/go-source-multiple/go-func-1/main.go
similarity index 100%
rename from tests/fixtures/go-source/go-func-2/go-func-2.go
rename to tests/fixtures/go-source-multiple/go-func-1/main.go
diff --git a/tests/fixtures/go-source-multiple/go-func-2/go-func-2.go b/tests/fixtures/go-source-multiple/go-func-2/go-func-2.go
new file mode 100644
index 0000000..8f61880
--- /dev/null
+++ b/tests/fixtures/go-source-multiple/go-func-2/go-func-2.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	fmt.Println("Hello, world!")
+}
diff --git a/tests/fixtures/go-source/go-func-2/go.mod b/tests/fixtures/go-source-multiple/go-func-2/go.mod
similarity index 100%
rename from tests/fixtures/go-source/go-func-2/go.mod
rename to tests/fixtures/go-source-multiple/go-func-2/go.mod
diff --git a/tests/fixtures/go-source/go-func-2/go.sum b/tests/fixtures/go-source-multiple/go-func-2/go.sum
similarity index 100%
rename from tests/fixtures/go-source/go-func-2/go.sum
rename to tests/fixtures/go-source-multiple/go-func-2/go.sum
diff --git a/tests/fixtures/rust-source/rust-func-2/.gitignore b/tests/fixtures/rust-source-multiple/rust-func-1/.gitignore
similarity index 100%
rename from tests/fixtures/rust-source/rust-func-2/.gitignore
rename to tests/fixtures/rust-source-multiple/rust-func-1/.gitignore
diff --git a/tests/fixtures/rust-source/rust-func-2/Cargo.lock b/tests/fixtures/rust-source-multiple/rust-func-1/Cargo.lock
similarity index 100%
rename from tests/fixtures/rust-source/rust-func-2/Cargo.lock
rename to tests/fixtures/rust-source-multiple/rust-func-1/Cargo.lock
diff --git a/tests/fixtures/rust-source/rust-func-2/Cargo.toml b/tests/fixtures/rust-source-multiple/rust-func-1/Cargo.toml
similarity index 100%
rename from tests/fixtures/rust-source/rust-func-2/Cargo.toml
rename to tests/fixtures/rust-source-multiple/rust-func-1/Cargo.toml
diff --git a/tests/fixtures/rust-source/rust-func-2/src/main.rs b/tests/fixtures/rust-source-multiple/rust-func-1/src/main.rs
similarity index 100%
rename from tests/fixtures/rust-source/rust-func-2/src/main.rs
rename to tests/fixtures/rust-source-multiple/rust-func-1/src/main.rs
diff --git a/tests/fixtures/rust-source-multiple/rust-func-2/.gitignore b/tests/fixtures/rust-source-multiple/rust-func-2/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/tests/fixtures/rust-source-multiple/rust-func-2/.gitignore
@@ -0,0 +1,1 @@
+/target
diff --git a/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.lock b/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.lock
new file mode 100644
index 0000000..ec2c4de
--- /dev/null
+++ b/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.lock
@@ -0,0 +1,713 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "async-stream"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "aws_lambda_events"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "663ef110325f68726f4bc51d12c610b9700f70e8bb8a55279cdeca01b12b5491"
+dependencies = [
+ "base64",
+ "bytes 0.5.6",
+ "chrono",
+ "http",
+ "http-serde",
+ "serde",
+ "serde_derive",
+ "serde_json",
+]
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
+[[package]]
+name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bytes"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "serde",
+ "time",
+ "winapi",
+]
+
+[[package]]
+name = "colored"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
+dependencies = [
+ "atty",
+ "lazy_static",
+ "winapi",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
+dependencies = [
+ "autocfg",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
+
+[[package]]
+name = "futures-task"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
+
+[[package]]
+name = "futures-util"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
+dependencies = [
+ "autocfg",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "proc-macro-hack",
+ "proc-macro-nested",
+ "slab",
+]
+
+[[package]]
+name = "hello"
+version = "0.1.0"
+dependencies = [
+ "aws_lambda_events",
+ "http",
+ "lambda_runtime",
+ "log",
+ "simple_logger",
+ "tokio",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "http"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11"
+dependencies = [
+ "bytes 1.0.1",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9"
+dependencies = [
+ "bytes 1.0.1",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-serde"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25698ac7002625796d5a7df8f0602400571da944c2edc1d5c268a6947dd4f692"
+dependencies = [
+ "http",
+ "serde",
+]
+
+[[package]]
+name = "httparse"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
+
+[[package]]
+name = "httpdate"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
+
+[[package]]
+name = "hyper"
+version = "0.14.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03"
+dependencies = [
+ "bytes 1.0.1",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
+name = "lambda_runtime"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9b08856997d11ca8122121b26b17a27ef1dce689d71ccd754e051f2417aebdd"
+dependencies = [
+ "async-stream",
+ "bytes 1.0.1",
+ "futures",
+ "http",
+ "hyper",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tokio-stream",
+ "tower-service",
+ "tracing",
+ "tracing-error",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+
+[[package]]
+name = "mio"
+version = "0.7.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
+dependencies = [
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "serde"
+version = "1.0.126"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.126"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "simple_logger"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd57f17c093ead1d4a1499dc9acaafdd71240908d64775465543b8d9a9f1d198"
+dependencies = [
+ "atty",
+ "chrono",
+ "colored",
+ "log",
+ "winapi",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
+
+[[package]]
+name = "socket2"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "time"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+dependencies = [
+ "libc",
+ "wasi",
+ "winapi",
+]
+
+[[package]]
+name = "tokio"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2602b8af3767c285202012822834005f596c811042315fa7e9f5b12b2a43207"
+dependencies = [
+ "autocfg",
+ "bytes 1.0.1",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "pin-project-lite",
+ "tokio-macros",
+ "winapi",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tower-service"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
+
+[[package]]
+name = "tracing"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "tracing-error"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48"
+dependencies = [
+ "sharded-slab",
+ "thread_local",
+ "tracing-core",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.toml b/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.toml
new file mode 100644
index 0000000..99de224
--- /dev/null
+++ b/tests/fixtures/rust-source-multiple/rust-func-2/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+edition = "2018"
+name = "hello"
+version = "0.1.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+aws_lambda_events = "0.4.0"
+http = "0.2.4"
+lambda_runtime = "0.3.0"
+log = "0.4.14"
+simple_logger = "1.11.0"
+tokio = "1.6.1"
diff --git a/tests/fixtures/rust-source-multiple/rust-func-2/src/main.rs b/tests/fixtures/rust-source-multiple/rust-func-2/src/main.rs
new file mode 100644
index 0000000..f8987cb
--- /dev/null
+++ b/tests/fixtures/rust-source-multiple/rust-func-2/src/main.rs
@@ -0,0 +1,29 @@
+use aws_lambda_events::event::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse};
+use aws_lambda_events::encodings::Body;
+use http::header::HeaderMap;
+use lambda_runtime::{handler_fn, Context, Error};
+use log::LevelFilter;
+use simple_logger::SimpleLogger;
+
+#[tokio::main]
+async fn main() -> Result<(), Error> {
+    SimpleLogger::new().with_level(LevelFilter::Info).init().unwrap();
+
+    let func = handler_fn(my_handler);
+    lambda_runtime::run(func).await?;
+    Ok(())
+}
+
+pub(crate) async fn my_handler(event: ApiGatewayProxyRequest, _ctx: Context) -> Result<ApiGatewayProxyResponse, Error> {
+    let path = event.path.unwrap();
+
+    let resp = ApiGatewayProxyResponse {
+        status_code: 200,
+        headers: HeaderMap::new(),
+        multi_value_headers: HeaderMap::new(),
+        body: Some(Body::Text(format!("Hello from '{}'", path))),
+        is_base64_encoded: Some(false),
+    };
+
+    Ok(resp)
+}
\ No newline at end of file
diff --git a/tests/main.js b/tests/main.js
index a2b11e9..57dec83 100644
--- a/tests/main.js
+++ b/tests/main.js
@@ -1352,7 +1352,10 @@ test('Adds `type: "functionsBundling"` to esbuild bundling errors', async (t) =>
 
     t.fail('Function did not throw')
   } catch (error) {
-    t.deepEqual(error.customErrorInfo, { type: 'functionsBundling', location: { functionName: 'function' } })
+    t.deepEqual(error.customErrorInfo, {
+      type: 'functionsBundling',
+      location: { functionName: 'function', runtime: 'js' },
+    })
   }
 })
 
@@ -1599,7 +1602,7 @@ test('Does not zip Go function files', async (t) => {
 test.serial('Does not build Go functions from source if the `buildGoSource` feature flag is not enabled', async (t) => {
   shellUtilsStub.callsFake((...args) => pWriteFile(args[1][2], ''))
 
-  const fixtureName = 'go-source'
+  const fixtureName = 'go-source-multiple'
   const { files } = await zipFixture(t, fixtureName, { length: 0 })
 
   t.is(files.length, 0)
@@ -1609,7 +1612,7 @@ test.serial('Does not build Go functions from source if the `buildGoSource` feat
 test.serial('Builds Go functions from source if the `buildGoSource` feature flag is enabled', async (t) => {
   shellUtilsStub.callsFake((...args) => pWriteFile(args[1][2], ''))
 
-  const fixtureName = 'go-source'
+  const fixtureName = 'go-source-multiple'
   const { files } = await zipFixture(t, fixtureName, {
     length: 2,
     opts: {
@@ -1647,12 +1650,35 @@ test.serial('Builds Go functions from source if the `buildGoSource` feature flag
   t.is(files[1].runtime, 'go')
 })
 
+test.serial('Adds `type: "functionsBundling"` to errors resulting from compiling Go binaries', async (t) => {
+  shellUtilsStub.callsFake(() => {
+    throw new Error('Fake error')
+  })
+
+  try {
+    await zipFixture(t, 'go-source', {
+      opts: {
+        featureFlags: {
+          buildGoSource: true,
+        },
+      },
+    })
+
+    t.fail('Expected catch block')
+  } catch (error) {
+    t.deepEqual(error.customErrorInfo, {
+      type: 'functionsBundling',
+      location: { functionName: 'go-func-1', runtime: 'go' },
+    })
+  }
+})
+
 test.serial(
   'Does not build Rust functions from source if the `buildRustSource` feature flag is not enabled',
   async (t) => {
     shellUtilsStub.callsFake((...args) => pWriteFile(args[1][2], ''))
 
-    const fixtureName = 'rust-source'
+    const fixtureName = 'rust-source-multiple'
     const { files } = await zipFixture(t, fixtureName, { length: 0 })
 
     t.is(files.length, 0)
@@ -1685,7 +1711,7 @@ test.serial('Builds Rust functions from source if the `buildRustSource` feature
     }
   })
 
-  const fixtureName = 'rust-source'
+  const fixtureName = 'rust-source-multiple'
   const { files } = await zipFixture(t, fixtureName, {
     length: 2,
     opts: {
@@ -1731,20 +1757,53 @@ test.serial('Builds Rust functions from source if the `buildRustSource` feature
   t.is(files[1].runtime, 'rs')
 })
 
+test.serial('Adds `type: "functionsBundling"` to errors resulting from compiling Rust binaries', async (t) => {
+  shellUtilsStub.callsFake((...args) => {
+    if (args[0] === 'cargo') {
+      throw new Error('Fake error')
+    }
+  })
+
+  try {
+    await zipFixture(t, 'rust-source', {
+      opts: {
+        featureFlags: {
+          buildRustSource: true,
+        },
+      },
+    })
+
+    t.fail('Expected catch block')
+  } catch (error) {
+    t.deepEqual(error.customErrorInfo, {
+      type: 'functionsBundling',
+      location: { functionName: 'rust-func-1', runtime: 'rs' },
+    })
+  }
+})
+
 test.serial('Throws an error with an informative message when the Rust toolchain is missing', async (t) => {
-  shellUtilsStub.throws()
+  shellUtilsStub.callsFake(() => {
+    throw new Error('Fake error')
+  })
 
-  const fixtureName = 'rust-source'
-  await t.throwsAsync(
-    zipFixture(t, fixtureName, {
+  try {
+    await zipFixture(t, 'rust-source', {
       opts: {
         featureFlags: {
           buildRustSource: true,
         },
       },
-    }),
-    { message: /^There is no Rust toolchain installed./ },
-  )
+    })
+
+    t.fail('Expected catch block')
+  } catch (error) {
+    t.true(error.message.startsWith('There is no Rust toolchain installed'))
+    t.deepEqual(error.customErrorInfo, {
+      type: 'functionsBundling',
+      location: { functionName: 'rust-func-1', runtime: 'rs' },
+    })
+  }
 })
 
 test('Does not generate a sourcemap unless `nodeSourcemap` is set', async (t) => {