Troubleshoot
This page describes common issues you may encounter when developing a snap, and how to resolve them.
If you encounter any issues that you can't solve on your own, please open a GitHub issue.
Fix build and evaluation issues
Because Secure ECMAScript (SES) adds additional restrictions
on the JavaScript runtime on top of strict mode, code that executes normally under strict mode might
not under SES.
mm-snap build
by default attempts to execute a snap in a stubbed SES environment.
You can also disable this behavior and run the evaluation step separately using mm-snap eval
.
If an error is thrown during this step, it's likely due to a SES incompatibility, and you must fix
the issues manually.
These incompatibilities tend to occur in dependencies.
While the errors you get from SES may seem scary, they're usually not that hard to fix.
The actual file, function, and variable names in the mm-snap eval
error stack trace might not make
a lot of sense to you, but the line numbers should correspond to your snap
bundle file.
Thus, you can identify if the error is due to your code or one of your dependencies.
If the problem is in a dependency, you can try a different version or to fix the issue locally by
using tools such as patch-package
(see how to
patch dependencies) or by modifying the bundle file directly.
To give you an idea of a common error and how to fix it, "sloppily" declared variables (i.e.
assigning to a new variable without an explicit variable declaration) are forbidden in strict mode,
and therefore in SES as well.
If you get an error during the eval
step that says something like variableName is not defined
,
simply prepending var variableName;
to your snap bundle may solve the problem.
(This actually happened so frequently with Babel's regeneratorRuntime
that
mm-snap build
automatically handles that one.)
Run mm-snap manifest --fix
if you modified your snap bundle after building.
Otherwise your manifest shasum
value won't be correct, and attempting to install your snap fails.
Use other build tools
If you prefer building your snap with a build system you're more comfortable with, Snaps implements plugins for several other build systems:
For examples on how to set up these build systems yourself, please see the examples.
We still recommend using the Snaps CLI to make sure your manifest shasum
value is correct, by
running mm-snap manifest --fix
after creating your bundle.
You may also benefit from running mm-snap eval
to detect any SES issues up front.
Patch dependencies
Some dependencies might make use of APIs that aren't available in the Snaps execution environment. To work around this, we recommend checking if another library is available that makes use of those APIs.
If you can't find another library (or version) that works with the Snaps execution environment, you
can patch the dependency yourself using patch-package
.
patch-package
allows you to make changes to your dependencies, saving the changes as a patch and
replaying it when installing dependencies.
Install patch-package
using Yarn:
yarn add -D patch-package postinstall-postinstall
Then add a postinstall script to your package.json
:
"scripts": {
+ "postinstall": "patch-package"
}
Now you can make changes to your dependencies inside node_modules
and run
yarn patch-package package-name
to save the changes as a patch.
This creates a .patch
file containing your dependency patch.
These patches can be committed to your Git repository and are replayed when you re-install your dependencies.
Patch the use of XMLHttpRequest
The XMLHttpRequest
API is not exposed in the Snaps execution environment and won't be in the future.
Because of this, you may run into issues with dependencies in your dependency tree attempting to
use this API for their network requests.
The following are examples of popular libraries that use XMLHttpRequest
and are thus not
compatible with the Snaps execution environment.
This section also describes patching strategies for fixing dependencies that try to use these libraries.
cross-fetch
cross-fetch
is a popular library used for cross-platform access to the fetch
API across multiple
environments.
Under the hood, however, the library uses XMLHttpRequest
and thus causes issues when used in a snap.
You can easily patch this issue using patch-package
.
Open node_modules/cross-fetch/browser-ponyfill.js
and find the following lines near the bottom of
the file:
// Choose between native implementation (global) or custom implementation (__self__)
// var ctx = global.fetch ? global : __self__;
var ctx = __self__; // this line disable service worker support temporarily
You can replace that with the following snippet:
// Choose between native implementation (global) or custom implementation (__self__)
var ctx = global.fetch
? { ...global, fetch: global.fetch.bind(global) }
: __self__;
// var ctx = __self__; // this line disable service worker support temporarily
After replacing it, run yarn patch-package cross-fetch
, which saves the patch for future use.
Alternatively, you can use the following patch, copy and paste it to
patches/cross-fetch+3.1.5.patch
, and re-install your dependencies:
diff --git a/node_modules/cross-fetch/dist/browser-ponyfill.js b/node_modules/cross-fetch/dist/browser-ponyfill.js
index f216aa3..6b3263b 100644
--- a/node_modules/cross-fetch/dist/browser-ponyfill.js
+++ b/node_modules/cross-fetch/dist/browser-ponyfill.js
@@ -543,8 +543,8 @@ __self__.fetch.ponyfill = true;
// Remove "polyfill" property added by whatwg-fetch
delete __self__.fetch.polyfill;
// Choose between native implementation (global) or custom implementation (__self__)
-// var ctx = global.fetch ? global : __self__;
-var ctx = __self__; // this line disable service worker support temporarily
+var ctx = global.fetch ? { ...global, fetch: global.fetch.bind(global) } : __self__;
+// var ctx = __self__; // this line disable service worker support temporarily
exports = ctx.fetch // To enable: import fetch from 'cross-fetch'
exports.default = ctx.fetch // For TypeScript consumers without esModuleInterop.
exports.fetch = ctx.fetch // To enable: import {fetch} from 'cross-fetch'
Using either of these methods allows your dependencies to access the fetch
API correctly and
cross-fetch
compatible with the Snaps execution environment.
axios
axios
is a popular networking library that uses XMLHttpRequest
under the hood.
Currently, there's no known way of patching axios
to work with the Snaps execution environment.
Instead, you must replace axios
with another library such as isomorphic-fetch
or
isomorphic-unfetch
, or simply use the Snaps execution environment global fetch
.
The following is an example of how you can rewrite your dependency to use fetch
instead of axios
.
In a production environment this may be a large task depending on the usage of axios
.
- axios
- fetch
const instance = axios.create({
baseURL: 'https://api.github.com/',
});
instance
.get('users/MetaMask')
.then((res) => {
if (res.status >= 400) {
throw new Error('Bad response from server');
}
return res.data;
})
.then((user) => {
console.log(user);
})
.catch((err) => {
console.error(err);
});
fetch('https://api.github.com/users/MetaMask')
.then((res) => {
if (!res.ok) {
throw new Error('Bad response from server');
}
return res.json();
})
.then((json) => console.log(json))
.catch((err) => console.error(err));
For more information, see how to replace axios with a simple custom fetch wrapper.