Wei-Shaw/sub2api · error · LiveAttestationUnavailableError
api_error
api_error
Error message
DeviceCheck is not supported on this Mac
What it means
Thrown by a JavaScript snippet embedded in backend/internal/platform/liveattestation/attestation_darwin.go. It calls a native addon's generateToken() (wrapping Apple DeviceCheck / DCDevice.generateToken) and throws when the result is falsy or result.supported is false, meaning the host Mac cannot produce a DeviceCheck token. DeviceCheck only works on real Mac hardware with macOS 10.15+, a signed app/binary with the proper Apple team, and working network access to Apple. In a VM, Hackintosh, CI runner, or unsigned dev build the addon commonly reports supported:false.
Source
Thrown at backend/internal/platform/liveattestation/attestation_darwin.go:270
function float(value) {
if (Number.isSafeInteger(value) && value >= 0) return uint(value);
const out = Buffer.allocUnsafe(9);
out[0] = 251;
out.writeDoubleBE(value, 1);
return out;
}
function array(values) { return Buffer.concat([head(128, values.length), ...values]); }
function map(entries) {
return Buffer.concat([head(160, entries.length), ...entries.flatMap(([key, value]) => [uint(key), value])]);
}
function field(key, value) { return Buffer.concat([text(key), text(value)]); }
function base64url(value) {
return value.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
}
(async () => {
const result = await addon.generateToken();
if (!result || !result.supported) throw new Error("DeviceCheck is not supported on this Mac");
if (!result.tokenBase64) throw new Error("DeviceCheck returned no token");
const fingerprint = map([
[0, uint(signals.schemaVersion)],
[1, array(signals.preferredLanguages.map(text))],
[2, text(signals.locale)],
[3, text(signals.timezone)],
[4, uint(signals.screenSizeSum)],
[5, float(signals.screenScale)],
[6, text(signals.appSessionId)]
]);
const fields = [
field("token", result.tokenBase64),
field("bundle_id", bundleID),
Buffer.concat([text("f"), head(64, fingerprint.length), fingerprint])
];
if (result.latencyMs != null) {
fields.push(Buffer.concat([text("t"), float(result.latencyMs)]));
}View on GitHub (pinned to 073e92d171)
Solutions
- Run the backend on a real, signed macOS host with macOS 10.15+ and verify addon.generateToken() returns supported:true in isolation.
- Check that the native addon binary and the host process are code-signed by the same team that configured the DeviceCheck capability in the Apple developer account.
- Add a preflight capability probe (call generateToken once at startup) and fall back to a non-attestation code path when supported is false instead of throwing mid-request.
- If running in CI or a VM, gate the attestation feature behind a config flag so those environments skip DeviceCheck.
Example fix
// before
const result = await addon.generateToken();
if (!result || !result.supported) throw new Error("DeviceCheck is not supported on this Mac");
// after
const result = await addon.generateToken();
if (!result || !result.supported) {
const err = new Error("DeviceCheck is not supported on this Mac");
err.code = 'DEVICECHECK_UNSUPPORTED';
throw err;
}
// caller:
try { token = await getAttestationToken(); }
catch (e) { if (e.code === 'DEVICECHECK_UNSUPPORTED') return skipAttestation(); throw e; } Defensive patterns
Strategy: fallback
Validate before calling
// Before starting attestation, probe once: const probe = await addon.generateToken(); export const deviceCheckAvailable = !!(probe && probe.supported);
Try / catch
try {
token = await getAttestationToken();
} catch (e) {
if (e instanceof Error && e.message.includes('DeviceCheck is not supported')) {
return skipAttestationGracefully(); // known-environment degradation
}
throw e;
} Prevention
- Gate DeviceCheck attestation behind a config flag so CI/VM environments skip it
- Code-sign the binary and addon with the team that owns the DeviceCheck capability
- Probe generateToken() at startup and cache the supported flag instead of failing per request
When it happens
Trigger: Calling the attestation flow on macOS where addon.generateToken() resolves with {supported:false} or an empty object. Specific causes: running on macOS < 10.15, inside a VM (DeviceCheck unsupported), missing/incorrect code-signing identity or entitlements for the native addon, no network path to Apple's DeviceCheck servers, or a Hackintosh without valid Secure Enclave/IMEI-era hardware support.
Common situations: Developers running the Go backend locally on an unsigned debug build; CI macOS runners (DeviceCheck frequently fails there); M-series Macs inside virtualization (UTM/Parallels); deployment where the binary is re-signed/ad-hoc signed and loses the original signing team.
Related errors
- live attestation is only supported when Sub2API runs on macO
- live attestation currently requires Apple Silicon; Intel mac
- ChatGPT DeviceCheck token generation timed out
- ChatGPT DeviceCheck returned a malformed attestation
- the installed ChatGPT app has an unexpected bundle identifie
AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15).
Data as JSON: /api/errors/ba13fdbd29373f51.
Report an issue: GitHub.