Tencent/matrix · critical

fatal error

Error message

fatal error: %s

What it means

swift::Demangle::unreachable() is the Demangler's internal 'impossible state' handler: it prints 'fatal error: <Message>' to stderr and calls std::abort(). The demangler calls it whenever a Node or encoded mangled-name structure violates invariants the demangler believes cannot occur, e.g. Node destructors on unexpected node kinds, or demangling paths for specializations, metatype representations, or impl parameter/result encodings that don't match expected shapes.

Solutions

  1. Match the demangler version to the Swift compiler version that produced the mangled names (sync KSCrash's Demangle.cpp with the app's Swift toolchain)
  2. Validate/sanitize symbol names before demangling; skip symbols that don't start with the expected Swift mangling prefix
  3. Update KSCrash/Matrix to a version with the demangler fix for that message
  4. If reproducible, report the demangling crash to swift/KSCrash upstream with the offending symbol

Example fix

// before
const char *mangled = symbol;
std::string demangled = swift::Demangle::demangleSymbolAsString(mangled);
// after
if (symbol && strncmp(symbol, "$s", 2) == 0) {
  std::string demangled = swift::Demangle::demangleSymbolAsString(symbol);
} else {
  const char *demangled = symbol; // leave undemangled
}
Defensive patterns

Strategy: type-guard

Validate before calling

bool isSwiftMangled(const char *s) { return s && (strncmp(s, "$s", 2) == 0 || strncmp(s, "_T0", 3) == 0); }

Type guard

static inline bool safeToDemangle(const char *symbol) {
  return symbol != nullptr && isSwiftMangled(symbol) && strlen(symbol) < 4096;
}

Try / catch

// demangler abort()s; cannot catch, so guard inputs and isolate:
if (safeToDemangle(sym)) {
  demangled = demangle(sym);
} else {
  demangled = sym; // fallback to raw symbol
}

Prevention

When it happens

Trigger: Parsing a corrupted or malformed Swift mangled symbol name that reaches an unsupported encoding path (demangleFuncSigSpecializationConstantProp, demangleMetatypeRepresentation, demangleImplParameterOrResult, isSimpleType), or a demangler bug while freeing/printing Node structures.

Common situations: Crash reporting symbolication (KSCrash CrashBlockMonitor) demangling stack frames from an unstripped Swift binary compiled by a different Swift version than the bundled demangler; hand-crafted or truncated symbol names fed to the demangler.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/a86c2c952fe4051f. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-iOS/Matrix/WCCrashBlockMonitor/KSCrash/swift/Basic/Demangle.cpp:42

#include "Demangle.h"
#include "Fallthrough.h"
#include "SwiftStrings.h"
#include "LLVM.h"
#include "Punycode.h"
//#include "UUID.h"
#include "Optional.h"
#include "StringRef.h"
#include <functional>
#include <inttypes.h>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace swift;
using namespace Demangle;

[[noreturn]] static void unreachable(const char *Message) {
    fprintf(stderr, "fatal error: %s\n", Message);
    std::abort();
}

DemanglerPrinter &DemanglerPrinter::operator<<(unsigned long long n) & {
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%" PRIu64, n);
    Stream.append(buffer);
    return *this;
}
DemanglerPrinter &DemanglerPrinter::operator<<(long long n) & {
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%" PRId64, n);
    Stream.append(buffer);
    return *this;
}

namespace {
struct QuotedString {

View on GitHub (pinned to 3b8293bd65)