eQuantic.UIeQuantic.UI
Docs
Playground
GitHub
DocsCompilation
Diagnostics
Edit this page
25 min read
Every build error and warning eqc can print, with what it means and what to do about it. The codes are stable: they are what you search for, and what a suppression would name.
This page is generated from the same reference the repository checks: docs/DIAGNOSTICS.md, held against the compiler by DiagnosticsDocumentedTests. A code raised by the compiler — or by the SDK's own MSBuild targets — with no row here fails the build, as does a row naming a code that no longer exists — and so does a code that gains a new reporting site, which is not a style rule: EQ2101 was once two unrelated errors (a resx translation mismatch and System.IO in a client component), each pinned by its own green test, because the two never met in one compilation.
Diagnostics print in MSBuild-canonical form, so the IDE and dotnet build both link them:
1
Pages/Counter.cs(14,9): error EQ2002: C# 'goto' cannot be transpiled to JavaScript …
EQ0xxx — the build host
The eqc process itself, before or around a compilation.
Code
Meaning
What to do
EQ0000
A compilation error arrived with no code of its own.
Read the message — the code is missing, not the diagnosis.
EQ0001
eqc crashed.
A bug in the compiler. The message carries the exception; please report it with the source that triggered it. One case is not the compiler's: the projects the app references could not be read from their source, because the list the SDK wrote for the build is not there or holds no project, or an assembly or a project it names is not there. The message names what did not hold, and the build stops there, since going on would write a page that names types nothing imports (Since 0.2.0-preview.62). Build again, and report it if it stays.
EQ0002
The MSBuild reference list is empty, so the semantic model would be built from an incomplete compilation and named arguments could be emitted in the wrong order.
Rebuild (dotnet build). If it persists, CompileEQuanticUI ran without FindReferenceAssembliesForReferences.
EQ1xxx — no translation exists yet
A gap in the compiler, not in your code. The construct is legal C# and could be translated; today nothing does it. These are the codes that shrink as the compiler grows.
Code
Meaning
What to do
EQ1001
A C# expression kind has no transpilation strategy.
Rewrite it in a transpilable form, or add a conversion strategy for the construct.
EQ1002
A C# statement kind has no transpilation strategy.
As above.
EQ1003
A C# node (neither expression nor statement) has no strategy.
As above.
EQ1004
A strategy matched the construct but this exact form has no emission — the translation would be silently wrong, so it stops.
Rewrite the form, or add the missing case to the strategy.
EQ1005
Two types share a twin filename — either the same name twice, or two names that differ only in case (one file on Windows and macOS). Their twins would be ONE file and the second would overwrite the first.
Rename one of the types.
EQ1006
(warning) One type is declared in more than one place and eqc emits one module per declaration, so the twin holds only the first declaration's members.
Combine them into a single declaration, or keep the members a component uses together in one. Harmless when the other halves are server-only, which is why it does not stop the build.
EQ1007
A method name declared twice in one type: two overloads, or two names that lower to one (Foo and foo). C# tells overloads apart by their parameters, and a JavaScript class has one member per name, so the twin would keep one of them and every call would reach it: a class, a record or a static class kept the LAST, a component the FIRST, all in silence. A static and an instance method may share a name, a partial method's two halves are one method, and an explicit interface implementation takes the interface's name, which no rename can change, so the overload check leaves it out; beside a default of another interface it takes its member's name like any member, and is checked. Two defaults a class takes from different interfaces, or a default and a member the class declares, land on one name the same way, and so do the same pairs along the class chain: a member a derived class declares on the name of a default its base takes (unless it implements that default's interface member, the class listing the interface again), a default on the name of a member a base declares, and two defaults of different interface members, one taken by a base and one by the derived class. An indexer takes two names on its twin, item for its getter and setItem for its setter, so a second indexer, or any member the twin holds on those names (a method, a field, a property, an event, a primary constructor's parameter a member reads) lands on the same member, and the message names what to rename. An explicit implementation of an interface's indexer holds item and setItem, which every access through the interface reaches, and the type's own indexer beside it takes names of its own; what an access through an interface cannot tell apart, two explicit implementations or one beside an indexer or a default that answers another interface, is refused. A record's or a struct's instance members that land on one name are refused too: its twin holds the state of each instance as properties of its own and its methods and computed properties on its prototype, so two of them shared one slot (struct S(int x) { public int X { get; } = x * 2; } answered 6|6 for 3|6) or the constructor wrote one over the other (readonly struct Money(decimal amount) { public decimal Amount => amount; } threw at new). A member the body declares under a positional parameter's own name is that parameter's property, and a primary constructor's parameter read only by an initializer is held by no instance (Since 0.2.0-preview.61). A plain class holds a primary constructor's parameter that a member reads the same way, so one that lands on another member's name is refused: class Greeter(string name) { public string Name => name.ToUpper(); } would answer the parameter for Name (Since 0.2.0-preview.61). A plain class's instance FIELD a case apart from another member is not refused: it moves to a slot of its own, value$ beside Value, every read and write of it reaches that slot, and the property, the method or the event keeps its name (Since 0.2.0-preview.61). Two parameters of a primary constructor that land on one name (x beside X) are refused on a class, a record and a struct alike: the twin's constructor names them camelCased, and a function cannot take two parameters of one name (Since 0.2.0-preview.61). A method that HIDES an inherited member, with new or with the same signature and no override, is no second method: its twin holds it under a name of its own (name$1), and a call bound to the hidden member keeps reaching it, so it is not refused; one that hides a member and answers an interface is, since a call through the interface reaches the hidden member's name (Since 0.2.0-preview.61). So does a method beside an explicit interface implementation of its name, which holds that name: one that also answers another interface is refused, since a call through that interface would reach the explicit one (Since 0.2.0-preview.61). A sequence's twin has one iteration and one current, so a type that implements IEnumerable<T>, or IEnumerator<T>, over two types is refused, since LINQ, a spread and a foreach over each of them would walk one sequence, and so is a non-generic GetEnumerator() or a Current the twin holds as one with the member it keeps, where it answers otherwise, which C# allows. One that hands back what that member answers (IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();, object IEnumerator.Current => Current;) answers alike, and is held as one (Since 0.2.0-preview.61).
Give each overload its own name, and keep one indexer (Compare and CompareLines); rename a record's or a struct's member that meets another (a private field _amount, a primary constructor's parameter by what it holds), and a class's primary constructor parameter that meets a member, or hold it in a field of your own (private readonly string _name = name;). Implement IEnumerable<T> over one type and hand another sequence out through a member of its own (public IEnumerable<string> Names => …), and return what the member the twin keeps returns from a non-generic GetEnumerator() or a Current, through it. The bound tree says which overload each call binds, so this is a gap the compiler can close by naming overloads apart, as it does user-defined operators.
EQ1008
A class relies on a default interface member of an interface compiled into a referenced assembly outside the SDK. JavaScript has no interfaces, so eqc writes each default a class takes into its twin: converted from the interface's source when the compilation has it, and delegated to the runtime's copy for the SDK's own interfaces (IAppTheme, ICodeLanguage, ICodeCompletionProvider), the public interfaces of the assemblies the runtime provides. Any other assembly's interface has neither, whatever namespace it declares, so the twin has no such member and a call to it in the browser would meet undefined. The same for a default that uses a static member of an interface, which has no JavaScript form to hold it.
Declare the member in the class, or keep the class out of client code.
EQ1009
A record's, a struct's or a plain class's constructor its twin cannot reach (a plain class's Since 0.2.0-preview.61). A JavaScript class has one constructor, so its twin takes a branch per C# constructor on how many arguments arrived, its optional parameters counted: each constructor that does its own work (the primary one, or an explicit one that does not chain with : this(…)) binds its parameters, sets the members, calls its base's constructor and runs its body, and each one that chains runs the one it chains to after evaluating the chain's arguments. A constructor that takes a count of arguments another one takes too cannot be told from it, and one that chains to a constructor that chains in turn, or : this() to a struct's implicit constructor beside constructors of its own, reaches its work through nothing. A record's copy constructor (protected R(R original)) is no branch: new never reaches it (Since 0.2.0-preview.61). Nor is the constructor only .NET's serialization calls, (SerializationInfo, StreamingContext), which Visual Studio's exception template writes beside (string, Exception): the browser has no SerializationInfo, and an exception class of the app's is a class whose constructors are checked as any class's are (Since 0.2.0-preview.61). A call of one the browser would make, a new, or the : base(…), : this(…) or base clause of a constructor the twin writes, is refused, since with no branch for it the call would run another constructor of two arguments (new Snap(info, context) ran Snap(string, string)); the template's own calls its base's, is no branch, and makes no call (Since 0.2.0-preview.61).
Give the constructor a count of arguments of its own, or chain it to one that does its own work. A static factory (static Coded FromText(string text) => new(text.Length)) says the same thing without a second constructor. Build an object whose serialization constructor a call reaches through another of its constructors.
EQ2001–EQ2014 — the construct cannot cross
Not a gap: there is no browser equivalent, or a translation would have to be a guess. These do not shrink with compiler work — they are the shape of the target.
Code
Meaning
What to do
EQ2001
A C# construct with no runtime equivalent in the browser (typed-reference intrinsics: __makeref, __reftype, __refvalue, stackalloc, pointers).
Restructure without it.
EQ2002
goto.
Restructure with loops and conditionals, or a labelled break/continue (those DO translate).
EQ2003
new T() on a type parameter — generic arguments are erased at runtime in JavaScript, so the concrete type is unknown.
Pass a factory (Func<T>) or the constructed value in.
EQ2004
A member with no JavaScript translation: an extension method whose declaring class is not part of this compilation, or a call the transpiler maps nothing for (Stopwatch.StartNew, Roslyn…) inside a class it mirrors, written qualified or reached bare through using static (WriteLine under using static System.Console, since 0.2.0-preview.60). Also a System.Range value stored rather than indexed with, or handed to an indexer that takes the Range itself (this[Range r], since 0.2.0-preview.61).
Use an instance member or bring the declaring source in; add a strategy; for a range, index with it directly (text[a..b]), or give the type a Length (or a Count) and a Slice(int start, int length), which a range calls; move the call behind a [ServerAction]; or, when the whole class only ever runs on the server, mark the CLASS [ServerOnly] and no module is emitted for it (0.2.0-preview.46).
EQ2005
An infinite iterator. Iterators are MATERIALISED into an array, so the loop would run forever instead of yielding lazily.
Give the loop an end (a bound, a yield break), or take what you need inside the method.
EQ2006
The member does not bind in the semantic model, so any translation would be a guess.
Either the code does not compile, or eqc is missing references / generated sources. Never guessed — see Compiler.
EQ2007
A comparer that changes what a collection considers equal or in order: a collection expression's with(…) argument beyond a capacity hint, or a comparer handed to a collection's constructor (new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase)) or to a LINQ operator that finds its keys or its elements by it (ToHashSet, and ToDictionary, ToLookup, GroupBy and Distinct since 0.2.0-preview.61). A list, a set or a dictionary finds an element by its type's default equality and takes no other: the default comparers and StringComparer.Ordinal pass. A sort or a binary search takes the type's default comparer, a Comparison<T>, a StringComparer's six, Comparer<T>.Create and a comparer you write, and refuses only one no twin carries (a StringComparer made for a culture, a comparer a library compiled).
Drop the comparer, or normalize the keys yourself (lower-case them on the way in and on every lookup). For a sort, pass a Comparison<T>.
EQ2008
Query syntax using join, let, a second from, or into — its C# translation runs through compiler-generated transparent identifiers. Also the fenced initializer forms.
Rewrite in method syntax, where every operator is supported.
EQ2009
A component is declared more than once in one file (partial declarations). eqc emits one module per declaration and cannot merge them.
Combine the members into a single declaration.
EQ2010
A symbol the framework keeps on the HOST — a type or a single member marked [ServerOnly] — named from client code. The runtime ships no twin, so the reference would compile, emit, and fail at hydration on "does not provide an export named" while SSR kept answering 200. An extension method called on a value that crosses names its home too: curve.Ease(t) is CurveEvaluator.Ease(curve, t), and it failed at the call. A type declared inside one that never crosses (a [ServerOnly] class or an attribute) has no twin either, as its owner has none, while one declared inside an exception class of the app's crosses as that class does, so client code that reaches it is refused the same way, however it reaches it: its name, an alias, using static, an operator or a conversion its value brings, or a zero. A module that would import its twin reports it at the declaration that holds the reference (Since 0.2.0-preview.61). A member marked [ServerOnly] is refused wherever client code names it, the code of its own type included: a component leaves such a method out of its twin, and its own Build calling it was a call to a member the twin does not have (Since 0.2.0-preview.62).
Call it from server code: a [ServerAction], a [ServerOnly] class, or a realizer. Never from a component's Build. Unlike EQ2004 this is a DECISION, not a gap — adding a strategy is not the answer.
EQ2011
A member that would take a name the runtime's component already uses. C# keeps a primary-constructor parameter, a field and a property apart, and spells them differently from the runtime's camelCase; JavaScript folds all of it onto this.<name>, so the assignment replaces the runtime's member and the page fails only in the browser. The list is read from the live runtime, never typed.
Rename the member. An override is exempt — a component's Build is meant to replace the runtime's build, and replacing a base member is what one is for — but a plain method is not: public void Mount() { } overrides nothing and still emits mount() over the runtime's own, so the component never mounts.
EQ2012
A [ServerAction] on an ABSTRACT component. The server registers an action under the name of the CONCRETE component carrying it — it skips abstract types and walks inherited methods — so it serves Tile/Load while a stub emitted on the base would invoke CardBase/Load. Nothing serves that id and the page gets "action not found", on both sides silently.
Declare the action on the concrete component. An alias is not the answer: the descriptor carries the component TYPE to invoke on, so two children inheriting one action give the base's id two answers — the owner of an inherited action is a decision, not a patch.
EQ2013
A vocabulary type whose browser half revives the values of a type argument (ServerTopic<T>) is built where that argument is, or holds, a type parameter, as in static ServerTopic<T> Topic<T>(string name) => new(name). JavaScript erases the type there, so the topic would carry no spec and every payload would reach its subscribers unrevived: a decimal or a long as the text the wire writes, a record without its members.
Build the topic where its payload type is concrete, as a static member of the type that declares the app's topics: static ServerTopic<RoomEvent> Room(string id) => new($"room:{id}"). See Server events.
EQ2014
An exception type is built or tested where a type argument it carries, its own or one of a type it is nested in, is, or holds, a type parameter, as in static Exception Of<T>() => new Failed<T>(), catch (Failed<T>), or new Missing() inside the generic class that declares it. An exception carries the types it is, which a typed catch, is and its name read, and JavaScript erases a type parameter, so the exception would carry, or the test compare, T itself: catch (Failed<int>) missed what Of<int>() threw (Since 0.2.0-preview.61).
Build and test an exception where its type arguments are concrete types, and declare an exception class outside a generic type.
EQ2100–EQ2101 — resx templates
The localization contract, checked on the build machine rather than when a visitor arrives.
Code
Meaning
What to do
EQ2100
About this call: the template must be a valid composite format whose specifiers are inside the supported subset, and the call must pass every hole it declares.
Fix the argument count, or drop the out-of-subset specifier (alignment such as {0,10} is outside v1).
EQ2101
About the translations: every culture's resx is held against the neutral one, which is the arity contract.
Fix the culture's template — a dropped or extra {n} fails the build, not the page.
EQ2102–EQ2107, EQ2112, EQ2114 — the client/server boundary
A client component reached for an API that only exists on a server, or for a value only the server has. The bridge is [ServerAction].
Code
Meaning
EQ2102
Direct database access (Microsoft.EntityFrameworkCore, System.Data).
EQ2103
Networking (System.Net.Http, System.Net.Sockets).
EQ2104
OS threading and locking (Thread, Monitor, Mutex, Semaphore — not Task).
EQ2105
Spawning processes (System.Diagnostics.Process).
EQ2106
Native interop / P-Invoke (System.Runtime.InteropServices).
EQ2107
Runtime IL generation (System.Reflection.Emit).
EQ2112
File-system access (System.IO).
EQ2114
A page uses a value the server's container gave it (a constructor parameter of a class type, or a member the page keeps one in) in a way the build cannot follow: a method called on it, the value passed where the build has no source, converted to text, compared, enumerated, stored in a collection, read through a member a .NET type declares on a value that does not cross whole (the Count of a list or a set of objects, a pair's Value), read through a type whose member of that name the value's own type hides (new), or read while the page is constructed. Such a value crosses to the browser as only what the browser reads of it, so a use the build cannot see would draw something else there. Reported by the source generator, so it shows in the editor. Decide on the server, in PrefetchAsync or a [ServerOnly] member, and keep the result in a field; or call a [ServerAction] when the browser's state is an input.
EQ2114 arrived in 0.2.0-preview.60, when a service the container hands a page stopped crossing whole (see Server Integration).
EQ2112 sits apart from its family on purpose: System.IO was reported as EQ2101 until that code turned out to belong to the resx check above, which the wiki already published. It is not a numbering slip to tidy back.
EQ2108–EQ2111 — one meaning per target, or none
The construct translates, but would READ differently on the server and in the browser. Rather than pick for you, eqc asks.
Code
Meaning
What to do
EQ2108
A CultureInfo the browser cannot follow: formatting crosses InvariantCulture and CurrentCulture, and reading a number (Parse/TryParse on any numeric type, Convert.ToInt32 and its siblings of a string, Convert.ToDecimal of a string or of a value that may hold one, such as an object) only InvariantCulture. Convert.ToBoolean never consults its provider but C# evaluates it, so it crosses InvariantCulture, CurrentCulture and a null, which are reads with no effect, and any other provider an app writes, while another CultureInfo (GetCultureInfo(name), new CultureInfo(name)), which may throw, has no twin to evaluate it. The culture is the property the provider binds to, however it is spelled: a member of another type that is also called InvariantCulture is refused, since it may return any culture.
Format with an explicit specifier (ToString("N2") follows the app's culture on both targets), or convert and read with the invariant culture.
EQ2110
A number read from text (or from a value that may hold text, such as an object) with no culture at all: C# reads in the request's culture ("1,5" is 1.5 in pt) and the browser in the invariant one. A number written as text needs no culture: both targets write the culture's text.
Say which you mean: pass CultureInfo.InvariantCulture.
EQ2111
GetService with no type argument to cross — the registry is keyed by the interface NAME, and there is nothing to key on.
Call the generic overload.
EQ2113
ConfigureAwait is dropped — there is one context to resume on — and dropping it would discard a NON-CONSTANT argument without evaluating it.
Pass a constant, or evaluate the expression into a local first.
EQ3001–EQ3005 — the Photon app generator
Code
Meaning
EQ3001
A Photon app has no program.
EQ3002
A Photon app has more than one program.
EQ3003
A capability's reason must be a constant.
EQ3004
An entitlement's key must be a constant — it is signed into the app at build time, so a key built at run time never reaches the signature.
EQ3005
A bundle fact must be constant — the Info.plist is written at build time, so an argument built at run time never reaches the app's manifest. Either argument counts, and whatever the method takes: a string, a bool, an AppCategory.
EQ3006
A Photon app writes its own entry point. The SDK generates one from CreateApp, so an app that kept its Main (or its top-level statements) has two — which the compiler reports as CS0017 against a generated file the app has never seen. Delete the app's: whatever it did first belongs in CreateApp, which is the only half Android runs.
EQ3101–EQ3105 — the source generators
The generated factory surface and form models.
Code
Meaning
EQ3101
A component elects more than one factory constructor ([UiFactory]).
EQ3102
Two components share a name.
EQ3103
A form model property has a type no text box can hold.
EQ3104
A validation attribute has no rule to become.
EQ3105
A [Compare] names a property this form does not have.
EQ4xxx — the SDK build
Raised by the SDK's own MSBuild targets, before or after the compiler runs.
Code
Meaning
What to do
EQ4001
The eQuantic icon tool — eqicon, which writes app icons, the vector catalog, the capability manifest and the macOS bundle — is missing where the SDK looks for it. In a build from the repository's source tree, eQuantic.UI.Native.Build did not build before this project: a broken build graph. From a package, the package shipped without tools/net10.0/eqicon.dll.
Neither is fixed by building twice. From source, the tool is a ProjectReference of every app project, so look at the errors above this one — the tool's own build failed — or at whoever removed the edge. From a package, clear the eQuantic cache (dotnet msbuild -t:ClearEQuanticCache), restore again, and report the package version if it persists.
EQ4002
The eQuantic compiler — eqc, which turns the app's components into JavaScript — is missing where the SDK looks for it: in a build from the repository's source tree, eQuantic.Build did not build before this project; from a package, the package shipped without tools/net10.0/eqc.dll; or an explicit EqcCliPath names a file that is not there. This used to be a warning, and a page with no JavaScript.
As EQ4001: not fixed by building twice. From source, read the errors above this one or restore the ProjectReference; from a package, clear the eQuantic cache and restore; with an explicit EqcCliPath, fix the path.
EQ4003
(warning) The app will be signed with a hardened-runtime exception (com.apple.security.cs.* — the family that relaxes a protection the hardened runtime imposes) while the build is not hardened. The key reaches the signature and the system never consults it. The SDK signs with --options runtime only when EQuanticHardenedRuntime is true, so any other non-empty value is an unhardened build — false, off, and the typo ture alike — and the message quotes back what was written. An EMPTY value is an ordinary development build and is never reported.
Set EQuanticHardenedRuntime=true, or drop the declaration. Not EQuanticSigningIdentity: that turns hardening on only where the property is empty, so it does not answer this. Note what this does NOT mean: the App Sandbox's permissions (com.apple.security.network.*, …files.*, …device.*) answer to PhotonEntitlements.AppSandbox, not to the hardened runtime, and an ad-hoc development build honours them — so they are never reported here.
EQ4004
A program the build started ended with an exit code other than zero and reported no error of its own: eqc, eqicon, bun, git, or on macOS codesign, ditto, notarytool, stapler or hdiutil. The message names the program and the arguments it was started with, as MSBuild's Exec named its command, except for a call whose command line is not echoed: the notary's, which carries a password. A program that reported its own errors, eqc's EQ codes for one, gets no EQ4004 after them.
Run the command the message names, from the project's folder, to see what the program says. A program that is not on the machine at all is MSBuild's own MSB6003.