SES_UNCAUGHT_EXCEPTION:{} in build process
The key problem is SES_UNCAUGHT_EXCEPTION: {} which unfortunately does not provide details about the actual exception.
Observed vs. Expected Behavior
- Observed: The snap build fails with an empty uncaught exception in the SES environment
- Expected: The build process should complete successfully or provide more details about the specific exception
Investigation Notes
- The warning about
Math.random()is not causing the build failure - it's just a warning about security best practices - The actual failure is likely due to one of our dependencies using code patterns that are incompatible with SES but for some reason I'm not getting any information about what the root cause is.
- The error mentions deprecated SES options (
dateTamingandmathTaming) but that should be unrelated to the build failure
Environment Information
- OS: macOS (darwin 24.3.0)
- Node.js Version: ≥ 18.6.0
- Package Manager: yarn v3.2.1
- MetaMask Snaps CLI Version: 6.6.0
- MetaMask Snaps SDK Version: 6.18.0
Build output:
juliustranquilli@Pixel-5 white-label % yarn build [site]: Process started [snap]: Process started [site]: success compile gatsby files - 0.512s success load gatsby config - 0.008s success load plugins - 0.108s success onPreInit - 0.001s success delete worker cache from previous builds - 0.002s success initialize cache - 0.011s success copy gatsby files - 0.044s success Compiling Gatsby Functions - 0.082s success onPreBootstrap - 0.091s success createSchemaCustomization - 0.000s success Clean up stale nodes - 0.004s - 1/0 0.00/s success Checking for changed pages - 0.000s success source and transform nodes - 0.039s info Writing GraphQL type definitions to [site]: /Users/juliustranquilli/webisoft/white-label/packages/site/.cache/schema.gql success building schema - 0.153s success createPages - 0.017s success createPagesStatefully - 0.047s info Total nodes: 27, SitePage nodes: 1 (use --verbose for breakdown) success Checking for changed pages - 0.000s success Cleaning up stale page-data - 0.001s success onPreExtractQueries - 0.000s success extract queries from components - 0.127s success write out redirect data - 0.001s success Build manifest and related icons - 0.078s success onPostBootstrap - 0.079s info bootstrap finished - 2.645s success write out requires - 0.002s success Building production JavaScript and CSS bundles - 0.703s success Building HTML renderer - 1.540s success Execute page configs - 0.025s success Caching Webpack compilations - 0.000s success run queries in workers - 0.002s - 0/0 0.00/s success Merge worker state - 0.001s info There are no new or changed html files to build. info There are no new or changed slice html files to build. success stitching slices - 0.000s success onPostBuild - 0.000s info Done building in 6.025864584 sec [site]: [site]: [site]: Pages [site]: [site]: └ src/pages/index.tsx [site]: └ / [site]: [site]: ╭────────────────────────────────────────────────────────────────╮ [site]: │ │ [site]: │ (SSG) Generated at build time │ [site]: │ D (DSG) Deferred static generation - page generated at runtime │ [site]: │ ∞ (SSR) Server-side renders at runtime (uses getServerData) │ [site]: │ λ (Function) Gatsby function │ [site]: │ │ [site]: ╰────────────────────────────────────────────────────────────────╯ [site]: [site]: Process exited (exit code 0), completed in 6s 339ms [snap]: - Checking the input file. [snap]: - Building the snap bundle. [snap]: - Evaluating the snap bundle. [snap]: ⚠ Compiled 659 files in 12354ms with 1 warning. [snap]: [snap]: • Math.randomwas detected in the Snap bundle. This is not a secure source of randomness, and should not be used in a secure context. Usecrypto.getRandomValuesinstead. [snap]: [snap]: ✖ Error: Failed to evaluate snap bundle in SES. This is likely due to an incompatibility with the SES environment in your snap. [snap]: Received the following error from the SES environment: [snap]: [snap]: SES The 'dateTaming' option is deprecated and does nothing. In the future specifying it will be an error. [snap]: SES The 'mathTaming' option is deprecated and does nothing. In the future specifying it will be an error. [snap]: SES_UNCAUGHT_EXCEPTION: {} [snap]: [snap]: at evaluate (/Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/commands/eval/implementation.cjs:22:19) [snap]: at process.processTicksAndRejections (node:internal/process/task_queues:105:5) [snap]: at async Object.task (/Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/commands/build/build.cjs:48:13) [snap]: at async /Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/utils/steps.cjs:34:32 [snap]: at async /Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/utils/steps.cjs:26:36 [snap]: at async executeSteps (/Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/utils/steps.cjs:25:9) [snap]: at async buildHandler (/Users/juliustranquilli/webisoft/white-label/node_modules/@metamask/snaps-cli/dist/commands/build/build.cjs:73:12) [snap]: Process exited (exit code 1), completed in 13s 789ms The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph Failed with errors in 13s 796ms
Hi there! Could you elaborate on what you are trying to do? Any specific dependencies you are bringing in? Usually SES errors like this occur with incompatible dependencies that need some workaround to work under SES
@FrederikBolding In this specific case I'm able to induce this error with a minimal example snap trying to import a specific library. The library source code is unavailable so it's not like we can dig into it, my concern was more so related to the snap-side handling of the incompatibility.
I figured it seems odd that we can induce an error like this which gives us no information whatsoever on how to reconcile. Normally with such incompatibility issues, the snap build process would list what the incompatibilities are, for example if you're importing a library which imports fs for filesystem access, the developer would be notified of this, and would then know that you need to polyfill or shim certain libraries. In this case there's just no recourse for the developer to try and manage the issue due to the lack of information. This is all contingent on the fact of course that I couldn't find any docs related to managing this error within the snap docs.
@FrederikBolding If it helps at all, I know this error gets thrown by implementation.cjs where the snaps CLI is evaluating the bundle for SES compatibility, the code in question is:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.evaluate = void 0;
const node_1 = require("@metamask/snaps-utils/node");
const chalk_1 = require("chalk");
const errors_1 = require("../../errors.cjs");
/**
* Evaluate the given bundle in the SES environment. This is a wrapper around
* {@link evalBundle} that throws a {@link CommandError} if the bundle cannot be
* evaluated.
*
* @param path - The path to the bundle.
* @returns The eval result.
* @throws If the bundle cannot be evaluated.
*/
async function evaluate(path) {
try {
return await (0, node_1.evalBundle)(path);
}
catch (evalError) {
if (evalError instanceof node_1.SnapEvalError) {
throw new errors_1.CommandError(`Failed to evaluate snap bundle in SES. This is likely due to an incompatibility with the SES environment in your snap.\nReceived the following error from the SES environment:\n\n${(0, node_1.indent)((0, chalk_1.red)(evalError.output.stderr), 2)}`);
}
// If the error is not a `SnapEvalError`, we don't know what it is, so
// we just throw it.
throw evalError;
}
}
exports.evaluate = evaluate;
//# sourceMappingURL=implementation.cjs.map
@floor-licker Can you share the minimal repro so we can look into this some more?
@FrederikBolding I could but the problem is there's really nothing to look at. All I'm doing is adding the dependency to the package.json and import their WalletBuilder module. It's just two lines of code added to the starter snap. I'm dealing with a private npm package of a chain that hasn't made their wallet builder open-source yet. I have to use a GitHub PAT to access their repo as opposed to through the NPM registry. Could that be what's causing the issue? Is there any way I could get a better look at the snaps SES configuration? I'm finding it somewhat unintuitive to understand exactly what restrictions are made.
@floor-licker If adding the dependency is the cause then it is likely that this dependency is throwing an uncaught error as a side-effect.
E.g. something like:
function foo(){
throw new Error("foo");
}
foo();
// Snap/dependency code proceeds here
This would trigger the uncaught exception handler, that being said, I don't have an explanation for why the error is an empty object, perhaps the library is throwing some non-standard errors that SES is not compatible with?
@FrederikBolding just to provide some closure, I was able to find out from the dev team of the wallet-sdk that it is indeed SES incompatible. The uncaught SES exception from snaps-cli is a bit odd, but this is not an issue with snaps-cli. If that wallet-idk repo gets open-sourced I'll link it here in case anyone is curious.
@FrederikBolding Just a follow up question that I thought made sense to leave in this thread for future developers:
In the case of dealing with a wallet SDK that is not SES-compatible, it seems like a possibility to come up with a middleware solution where the wallet-sdk is hosted on a local server, and the snap then interfaces with the wallet-sdk via that server, either through websockets or JSON RPC.
Although this seems like it could be a solution for the SES-incompatibility issue, I'm just curious as to whether there is any point to this solution since it's essentially circumventing the deliberately placed security measures of the SES-environment. Is it likely that this sort of solution pass an audit?
It's hard to say anything conclusive without knowing exactly what the problem is. Some incompatibilities can be worked around even inside the Snap itself by patching the dependency. Others may require changes on our end, which we regularly do to add safe to expose JavaScript globals that may not already be available.
So all in all, it depends 😄
@floor-licker Are you still having issues or did you figure this out?
@FrederikBolding Thanks for checking in. It’s a bit much for a GitHub comment chain, but in short: we suspect the SES incompatibility originates in the chain’s own SDKs. We reviewed the source code and this seems plausible. Many chains build core wallet SDKs in other languages and compile them to JS via third-party tools, meaning they can't control the exact JS output and can’t guarantee SES-safe features.
At this point, my take is that the SDK either needs to (a) emit JS in a way that gives us fine-grained control over the features used (e.g., avoiding forbidden globals, dynamic eval, etc.), or (b) avoid emitting JS altogether by compiling to a WASM binary with a clean interface.
You may be able to patch the dependency if you can figure out what incompatibility is. I recommend keeping up to date with our latest CLI etc which may have improvements to help debug these types of problems in the future. Will close for now, but feel free to open another issue if needed.