Skip to main content
Version: V3

Troubleshooting

If these suggestions do not work, feel free to ask in the Semaphore Discussions or in the dev-chat channel in the Semaphore Discord.

Using Semaphore in the frontend​

Semaphore works with any JavaScript frontend framework, but the @semaphore-protocol/proof package is using snarkjs, which uses Node.js modules which are not compatible with frontend frameworks and there are some changes that we need to do to make it work on the client side.

Semaphore with Nextjs​

You will see an error like this:

Module not found: Can't resolve 'fs'

To solve this, in your next.config.js file, inside the nextConfig object, add:

webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
fs: false
}
}

return config
}

Your next.config.js file would be something like this:

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
fs: false
}
}

return config
}
}

module.exports = nextConfig

Semaphore with React + Vite or Vuejs + Vite​

You will see an error like this:

readman.js:43 Uncaught ReferenceError: process is not defined
at stringToBase64 (threadman.js:43:5)
at threadman.js:50:22

To solve that:

1- Install @esbuild-plugins/node-globals-polyfill and @esbuild-plugins/node-modules-polyfill

npm install @esbuild-plugins/node-globals-polyfill
npm install @esbuild-plugins/node-modules-polyfill

2- Modify the vite.config.ts to add them:

import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"
import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill"

and in defineConfig add:

optimizeDeps: {
esbuildOptions: {
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true
}),
NodeModulesPolyfillPlugin()
]
}
}

Your vite.config.ts should be something like:

import { fileURLToPath, URL } from "node:url"

import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"

import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"
import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill"

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url))
}
},
optimizeDeps: {
esbuildOptions: {
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true
}),
NodeModulesPolyfillPlugin()
]
}
}
})
info

In case of React with Vite, if you see a red wavy underline on every Semaphore module which says Could not find a declaration file for module ..., change the moduleResolution from bundler to Node in the tsconfig.json file inside compilerOptions.

Your tsconfig.json file would be something like this:

{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "Node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

Semaphore Groups​

Creating a Group​

When you create a group and the transaction is reverted, make sure that the group id you are using does not exist on the network you are using.

To check that, you can use the Semaphore CLI with the command get-groups and the network you are using and then, make sure that your group id is not part of that list. You can also use the Semaphore explorer.

Semaphore Proofs​

Transaction reverted when using the same external nullifier​

When you generate a proof using the same external nullifier you used to verify a proof before, the transaction will be reverted because that external nullifier was already used. If you want to send and verify several proofs from the same identity, you should use a different external nullifier each time you generate a proof.