Note
Diagnostic codes are stable identifiers. Once assigned, a code number always refers to the same
diagnostic, even across compiler versions. The canonical list of codes lives in
Tyhp/Domain/Exceptions/MessageCode.cs.
Tier 1 · Story 14Complete
This page is the comprehensive index of Tyhp compiler diagnostic codes. Every entry is
generated from the compiler's code registry (MessageCode.cs) and the localized short-message
catalog (.resx), so the message text always matches what the compiler emits.
Diagnostic codes are stable identifiers. Once assigned, a code number always refers to the same
diagnostic, even across compiler versions. The canonical list of codes lives in
Tyhp/Domain/Exceptions/MessageCode.cs.
Run tyhp --explain TYHP#### (or tyhp explain ####) to print the
long-form explanation for any code. That command reads the same dynamic catalog as this page.
tyhp --explain TYHP4008
tyhp explain 4008
tyhp explain --code=TYHP3003
Parser errors occur during the ANTLR4 lexing and parsing phase when the compiler encounters syntax it cannot understand.
TYHP1001 (Error, Warning)ParserUnknownError. Message: Unknown parser error: {0}.
A catch-all for parser/lexer errors that do not match a more specific code. The {0} placeholder contains the underlying error message from the ANTLR4 parser.
<?tyhp
// Invalid token that confuses the lexer
class #invalid { }
Fix: Examine the indicated line and column for syntax errors. Ensure all tokens are valid Tyhp/PHP syntax.
TYHP1002 (Error)ParserUnexpectedError. Message: Unexpected token .{0} at position {1}
The parser encountered a token it did not expect at the current position. This usually indicates a missing semicolon, unmatched brace, or misplaced keyword.
<?tyhp
function greet(string $name) string {
// Missing colon before return type ^^^
return "Hello, $name";
}
Fix: Check the line for missing punctuation (semicolons, colons, braces, parentheses) or misplaced keywords. The correct syntax above is function greet(string $name): string.
TYHP1003 (Error)ParserCompileAborted. Message: Compilation aborted: {0}.
The parser encountered too many errors and aborted processing for the current file. Earlier errors in the same file typically cause this.
Fix: Fix the earlier parser errors in the same file and recompile. Once the foundational syntax issues are resolved, this error will no longer appear.
TYHP1004 (Error)LexerCloseTagNotAllowedInTaglessMode. Message: Closing tag .?> is not allowed when source.tagless is enabled
Run tyhp --explain TYHP1004 for the long-form explanation.
Visitor errors occur during parse-tree to AST conversion when the visitor encounters an unexpected structure or unsupported construct.
TYHP2001 (Error)VisitorUnknownError. Message: Unknown visitor error.
A catch-all for unexpected errors during AST generation. This typically indicates an internal compiler issue.
Fix: If you encounter this error, simplify the code near the indicated location and try again. If the error persists, please report it as a compiler bug.
TYHP2002 (Error)VisitorUnexpectedAlternative. Message: Unexpected grammar alternative .{1} in rule {0}
The visitor hit an unexpected grammar alternative while walking the parse tree (a production the AST builder does not handle). This may occur with unusual or edge-case syntax combinations.
Fix: Simplify the expression or statement. If the syntax is valid PHP/Tyhp, this may indicate a compiler limitation -- please report it.
TYHP2003 (Error)VisitorMissingRequiredNode. Message: Required AST node missing in rule .{0}
A required component of a language construct was not found in the parse tree. This often results from incomplete or malformed syntax.
<?tyhp
// Missing class body
class User
Fix: Ensure the construct is syntactically complete. Classes need bodies ({ }), functions need parameter lists and bodies, etc.
TYHP2004 (Error)VisitorUnsupportedConstruct. Message: Language construct .{0} is not yet supported
The code uses a PHP language construct that the Tyhp compiler does not yet support.
Fix: Use an alternative approach that is supported by the compiler. Check the Tyhp documentation for supported constructs and any known limitations.
Binder errors occur during symbol resolution and scope management.
TYHP3001 (Error, Warning)BinderUnknownError. Message: Unknown binder error: {0}.
A catch-all for unexpected errors during the binding phase.
Fix: If you encounter this error, please report it as a compiler bug with a minimal reproduction.
TYHP3002 (Error)BinderDuplicateSymbolDeclaration. Message: Duplicate declaration of symbol .{0}
Two declarations with the same name exist in the same scope. This includes classes, functions, constants, and variables declared at the same scope level.
The primary span is the later declaration. A secondary span labeled "declared here" points at the first declaration of that name.
<?tyhp
class User { } // first declaration — labeled "declared here"
class User { } // Error: Duplicate declaration of symbol `User`
Fix: Rename one of the duplicate declarations, or remove the duplicate. If the declarations are in different files, ensure they are in different namespaces.
TYHP3003 (Error)BinderSymbolNotFound. Message: Symbol .{0} is not found
A referenced class, function, constant, variable, or other symbol could not be resolved in any accessible scope. Type names on is / instanceof / typeof, and undeclared names inside generic type arguments, use this same diagnostic.
<?tyhp
function demo(mixed $x): bool {
return $x is UnknownType; // Error: Symbol `UnknownType` is not found
}
Fix: Add a use statement to import the symbol, check for typos in the name, verify the symbol is defined in a loaded tyhpdef file, or ensure the file defining the symbol is included in the project.
TYHP3004 (Error)BinderInvalidSymbolTypeForParent. Message: Symbol type .{0} is not valid for parent scope {1}
A symbol was declared in a scope where that type of declaration is not allowed.
Fix: Move the declaration to an appropriate scope. For example, class declarations belong at the namespace level, not inside function bodies.
TYHP3005 (Error)BinderInvalidFileScopeArgument. Message: Invalid argument for file scope.
An internal error indicating an invalid configuration was passed to the file scope during binding.
TYHP3006 (Error)BinderCircularInheritance. Message: Circular inheritance detected involving .{0}
A class or interface directly or indirectly extends or implements itself, creating an inheritance cycle.
<?tyhp
class A extends B { }
class B extends A { } // Error: Circular inheritance
Fix: Break the inheritance cycle by removing or restructuring the class hierarchy.
TYHP3007 (Error)BinderTraitConflict. Message: Trait method conflict: .{0}
Two or more traits used by the same class declare methods with the same name, and no conflict resolution (insteadof or as) was provided.
<?tyhp
trait A { public function hello(): void { } }
trait B { public function hello(): void { } }
class MyClass {
use A, B; // Error: Trait method conflict: 'hello'
}
Fix: Use insteadof to resolve the conflict: use A, B { A::hello insteadof B; }.
TYHP3008 (Error)BinderDuplicateUseAlias. Message: Duplicate use alias .{0}
Two use import statements bring in symbols with the same alias name.
<?tyhp
use App\Models\User;
use App\DTOs\User; // Error: Duplicate use alias 'User'
Fix: Use an alias to disambiguate: use App\DTOs\User as UserDTO;.
TYHP3009 (Error)BinderInvalidSelfReference. Message: Invalid .self reference outside of a class
The keyword self was used outside of a class, interface, trait, or enum body.
Fix: Use self only within class-like declarations. Outside of a class, use the fully-qualified class name instead.
TYHP3010 (Error)BinderInvalidParentReference. Message: Invalid .parent reference: class has no parent
The keyword parent was used in a class that does not extend another class.
<?tyhp
class Standalone {
public function test(): void {
parent::test(); // Error: class has no parent
}
}
Fix: Add an extends clause to the class, or remove the parent reference.
TYHP3011 (Error)BinderDuplicateGenericParameter. Message: Duplicate generic type parameter .{0}
A generic class or function declares two type parameters with the same name.
<?tyhp
class Container<T, T> { } // Error: Duplicate generic type parameter 'T'
Fix: Give each generic type parameter a unique name.
TYHP3012 (Error)BinderGenericParameterShadow. Message: Generic type parameter .{0} shadows an existing type
A generic type parameter has the same name as an existing class, interface, or type alias in scope.
Fix: Rename the generic type parameter to avoid shadowing (e.g., use TItem instead of User).
TYHP3013 (Error)BinderMultipleConstructors. Message: Class .{0} declares multiple constructors
A class declares more than one __construct method. PHP and Tyhp only allow a single constructor per class.
Fix: Merge the constructors into a single __construct method with optional parameters, or use static factory methods for alternative construction patterns.
TYHP3014 (Error)ExtensionOperatorMissingTarget. Message: Operator overload in an extension is missing the required .<Type> target
An operator declared inside an extension body must specify the type it extends using the <Type> target syntax.
TYHP3015 (Error)ExtensionOperatorTargetNotAllowed. Message: .<Type> on an operator overload is only allowed inside an extension declaration
The <Type> target on an operator is only valid within an extension declaration, not on a class-member operator.
TYHP3016 (Error)ExtensionOperatorTargetNotFound. Message: The .<Type> target of an extension operator does not resolve to a class or built-in type
The type named as the target of an extension operator overload does not resolve to a known class.
TYHP3017 (Error)BinderUnresolvedExtendsType. Message: Extends type .{0} is not resolved
Run tyhp --explain TYHP3017 for the long-form explanation.
TYHP3018 (Error)BinderUnresolvedImplementsType. Message: Implements type .{0} is not resolved
Run tyhp --explain TYHP3018 for the long-form explanation.
TYHP3019 (Error)BinderUnresolvedReturnType. Message: Return type .{0} is not resolved
Run tyhp --explain TYHP3019 for the long-form explanation.
TYHP3020 (Error)BinderUnresolvedParameterType. Message: Parameter type .{0} is not resolved
Run tyhp --explain TYHP3020 for the long-form explanation.
TYHP3021 (Error)BinderUnresolvedGenericConstraintType. Message: Generic constraint type .{0} is not resolved
Run tyhp --explain TYHP3021 for the long-form explanation.
TYHP3022 (Error)BinderUnresolvedGenericDefaultType. Message: Generic default type .{0} is not resolved
Run tyhp --explain TYHP3022 for the long-form explanation.
TYHP3023 (Error)BinderInvalidExtendsTypeKind. Message: Extends type .{0} is a {1}, not a {2}
Run tyhp --explain TYHP3023 for the long-form explanation.
TYHP3024 (Error)BinderInvalidImplementsTypeKind. Message: Implements type .{0} is a {1}, not an interface
Run tyhp --explain TYHP3024 for the long-form explanation.
TYHP3025 (Error)ExtensionOperatorTargetNotInstantiable. Message: The .<Type> target of an extension operator cannot be {0}
The target of an extension operator must be a class or a value-bearing built-in type such as string, int, or array. Types that cannot be instantiated or used as a runtime value (void, never, null, mixed, resource, true, false) are not valid targets.
TYHP3026 (Error)BinderExternExtendsType. Message: Extends type .{0} is extern
A type extends an extern placeholder. That name is bound, so this is not an unresolved extends (TYHP3017). Placeholders cannot be inheritance bases: a real tyhpdef class or interface must not extend an extern type.
The primary span is the extends clause. A secondary span labeled "declared here" points at the extern declaration. When that declaration has // @provided-by: tyhpdef/ruflin-elastica or // @provided-by: tyhpdef/php-ext-curl, help cites that wrapper name as-is.
Omit generated types that would extend an extern (for example a test base). Include the providing tyhpdef/* package if the intent is a real parent type.
TYHP3027 (Error)BinderExternImplementsType. Message: Implements type .{0} is extern
A type implements an extern placeholder. That name is bound, so this is not an unresolved implements (TYHP3018). Placeholders cannot be interface lists: a real tyhpdef class or enum must not implement an extern type.
The primary span is the implements clause. A secondary span labeled "declared here" points at the extern declaration. When that declaration has // @provided-by: tyhpdef/ruflin-elastica or // @provided-by: tyhpdef/php-ext-curl, help cites that wrapper name as-is.
Omit generated types that would implement an extern. Include the providing tyhpdef/* package if the intent is a real interface.
TYHP3028 (Error)BinderTypeAliasConflictsWithFunction. Message: Type alias .{0} conflicts with a function of the same name
Run tyhp --explain TYHP3028 for the long-form explanation.
TYHP3029 (Error)BinderCircularTypeAlias. Message: Circular type alias .{0}
Run tyhp --explain TYHP3029 for the long-form explanation.
TYHP3030 (Error)BinderTypeAliasReservedFunctionName. Message: Type alias .{0} cannot be a PHP function name
Run tyhp --explain TYHP3030 for the long-form explanation.
Checker errors occur during type checking and semantic analysis.
TYHP4001 (Error)CheckerUnknownError. Message: Unknown checker error: {0}.
A catch-all for unexpected errors during the checking phase.
TYHP4002 (Error)CheckerMultipleVisibilities. Message: .{0} cannot have multiple visibility modifiers
A class member has multiple visibility keywords (public, protected, private).
<?tyhp
class Example {
public protected string $name; // Error: Multiple visibility modifiers
}
Fix: Use only one visibility modifier per declaration.
TYHP4003 (Error)CheckerNotAllowedMemberModifier. Message: Modifier .{0} is not allowed here
A modifier is used in a context where it is not valid.
<?tyhp
interface Cacheable {
static function getCacheKey(): string;
// Error: 'static' is not allowed on interface methods
}
Fix: Remove the disallowed modifier. Check what modifiers are valid for the current context (interface, trait, enum, etc.).
TYHP4004 (Error)CheckerAccessorVisibilityCannotBeMoreVisibleThanProperty. Message: Accessor visibility cannot be more visible than property visibility; .{0} is more visible than {1}
A property hook's (get/set) visibility is more permissive than the property itself.
<?tyhp
class Example {
private string $name {
public get => $this->name; // Error: accessor more visible than property
}
}
Fix: Make the accessor visibility equal to or more restrictive than the property visibility.
TYHP4005 (Error)CheckerMemberModifierConflict. Message: Member modifier .{0} cannot be used at the same time as {1}
Two modifiers on the same declaration are mutually exclusive.
<?tyhp
class Example {
abstract final function process(): void;
// Error: Conflicting modifiers: 'abstract' and 'final'
}
Fix: Remove one of the conflicting modifiers. A method cannot be both abstract and final.
TYHP4006 (Error)CheckerInvalidPropertyAccessorType. Message: Invalid property accessor type .{0}
The property hook type is not recognized (must be get or set).
TYHP4007 (Error)CheckerParameterNotAllowedOnPropertyAccessorType. Message: Parameter declaration is not allowed on property accessor of type .{0}
A get accessor declares a parameter, which is not valid. Only set accessors accept a value parameter.
TYHP4008 (Error)CheckerTypeMismatch. Message: Cannot assign type .{0} to type {1}
The checker reports a type mismatch when a value's type is not assignable to the type its target declares — an assignment, an argument, a return statement, or a property initializer. The first placeholder is the type of the value being supplied; the second is the type the target requires.
<?tyhp
int $count = "hello";
// Error: Cannot assign type 'string' to type 'int'
Make the two types agree: widen or change the declared type, convert the value explicitly, or narrow a nullable or union type with a guard before the assignment.
TYHP4009 (Error)CheckerIncompatibleReturnType. Message: Return type .{0} is not compatible with declared return type {1}
A function or method returns a value whose type does not match its declared return type.
<?tyhp
function getName(): string {
return 42; // Error: Return type 'int' is not compatible with 'string'
}
Fix: Change the return value to match the declared return type, or update the return type declaration.
TYHP4010 (Error)CheckerIncompatibleArgumentType. Message: Argument of type .{0} is not assignable to parameter of type {1}
A function or method call passes an argument whose type does not match the expected parameter type.
<?tyhp
function process(int $id): void { }
process("abc"); // Error: Argument of type 'string' not assignable to 'int'
Fix: Pass a value of the correct type, or cast the argument explicitly.
TYHP4011 (Error)CheckerMissingReturnStatement. Message: Function with return type .{0} must return a value on all code paths
A non-void function has code paths that do not return a value.
<?tyhp
function getStatus(bool $active): string {
if ($active) {
return "active";
}
// Error: not all code paths return a value
}
Fix: Add a return statement for every code path, including else branches and after loops.
TYHP4012 (Warning)CheckerUnreachableCode. Message: Unreachable code detected.
Code exists after a return, throw, break, continue, or exit statement and will never execute.
<?tyhp
function example(): string {
return "done";
echo "this never runs"; // Warning: Unreachable code
}
Fix: Remove the unreachable code or restructure the control flow.
TYHP4013 (Error)CheckerVariableUsedBeforeAssignment. Message: Variable .${0} is used before being assigned
A variable is read before it has been assigned a value on any code path.
<?tyhp
function example(): void {
echo $x; // Error: Variable '$x' is used before being assigned
int $x = 5;
}
Fix: Assign the variable before using it.
TYHP4014 (Error)CheckerVariablePossiblyUndefined. Message: Variable .${0} is possibly undefined
A variable may not be defined on all code paths leading to its use.
<?tyhp
function example(bool $flag): void {
if ($flag) {
string $msg = "yes";
}
echo $msg; // Error: '$msg' is possibly undefined
}
Fix: Initialize the variable before the conditional, or add an else branch that also assigns it.
TYHP4015 (Error)CheckerVariablePossiblyNull. Message: Variable .${0} is possibly null here but is used where a non-null value is required
A variable with a nullable type is used in a context that requires a non-null value without a prior null check.
<?tyhp
function example(?string $name): void {
echo \strlen($name); // Warning: '$name' is possibly null
}
Fix: Add a null check before using the variable, or use the null coalescing operator ??.
TYHP4016 (Error)CheckerVariableTypeRequired. Message: .{0} must have a type annotation or inferable initializer
A variable, parameter, or property lacks both an explicit type declaration and an initializer from which the type can be inferred. A function or method with no return type uses the same diagnostic with the subject return type.
<?tyhp
function example($x) {
return $x;
}
Fix: Annotate the parameter and return type (function example(int $x): int). For a local variable, add an explicit type (int $x;) or an initializer ($x = 0;).
TYHP4017 (Error)CheckerAbstractMethodNotImplemented. Message: Class .{0} does not implement abstract method {1} from {2}
A concrete class extends an abstract class but does not implement all of its abstract methods.
<?tyhp
abstract class Shape {
abstract public function area(): float;
}
class Circle extends Shape {
// Error: does not implement abstract method 'area' from 'Shape'
}
Fix: Implement all abstract methods from the parent class with matching signatures.
TYHP4018 (Error)CheckerInterfaceMethodNotImplemented. Message: Class .{0} does not implement interface method {1} from {2}
A class implements an interface but does not provide implementations for all of its methods.
TYHP4019 (Error)CheckerFinalClassExtended. Message: Cannot extend final class .{0}
A class attempts to extend a class that is declared as final.
<?tyhp
final class Singleton { }
class MySingleton extends Singleton { } // Error: Cannot extend final class
TYHP4020 (Error)CheckerFinalMethodOverridden. Message: Cannot override final method .{0}
A subclass attempts to override a method that is declared as final in the parent class.
TYHP4021 (Error)CheckerReadonlyPropertyReassigned. Message: Cannot assign to readonly property .{0}
A readonly property is being assigned outside of the constructor.
<?tyhp
class User {
public function __construct(
public readonly string $name
) {}
public function rename(string $newName): void {
$this->name = $newName; // Error: Cannot assign to readonly property
}
}
TYHP4022 (Error)CheckerAbstractClassInstantiated. Message: Cannot instantiate abstract class .{0}
Code attempts to create an instance of an abstract class with new.
TYHP4023 (Error)CheckerEnumCaseTypeMismatch. Message: Enum case value type .{0} does not match backed type {1}
A backed enum case has a value of a type that does not match the enum's backing type.
<?tyhp
enum Status: string {
case Active = 1; // Error: int value for string-backed enum
}
TYHP4024 (Error)CheckerEnumMethodNotAllowed. Message: Enum cannot have a constructor.
An enum declares a method that is not allowed (e.g., a constructor).
TYHP4025 (Error)CheckerMemberNotAccessible. Message: .{0} is {1} and cannot be accessed from {2}
A private or protected member is accessed from outside its allowed scope.
<?tyhp
class Account {
private float $balance = 0.0;
}
Account $a = new Account();
$a->balance; // Error: Cannot access private member 'balance'
TYHP4026 (Error)CheckerBreakOutsideLoop. Message: .break statement is not within a loop or switch
A break statement appears outside of a for, foreach, while, do-while, or switch block.
TYHP4027 (Error)CheckerContinueOutsideLoop. Message: .continue statement is not within a loop
A continue statement appears outside of a loop construct.
TYHP4028 (Error)CheckerAwaitOutsideAsync. Message: .await can only be used inside an async function
The await keyword is used inside a function that is not marked as async.
<?tyhp
function fetchData(): string {
return await getRemoteData(); // Error: await outside of async function
}
Fix: Mark the function as async: async function fetchData(): Promise<string>.
TYHP4029 (Error)CheckerInvalidOperatorForType. Message: Operator .{0} cannot be applied to types {1} and {2}
A binary or unary operator is used with operands whose types do not support that operation.
TYHP4030 (Error)CheckerDisposableRequiresInterface. Message: Disposable assignment .:= requires type implementing IsDisposable
The disposable assignment operator := is used with a type that does not implement the IsDisposable interface.
<?tyhp
class PlainObject { }
$obj := new PlainObject();
// Error: ':=' requires the type to implement IsDisposable
TYHP4031 (Error)CheckerWithKeywordInvalidProperty. Message: Property .{0} does not exist on type {1}
The with keyword references a property name that does not exist on the target type.
TYHP4032 (Error)CheckerTypeGuardInvalidReturn. Message: Type guard function must return .bool
A function with a type guard return type ($param is Type) does not return a boolean value.
TYHP4035 (Error)CheckerGenericConstraintNotSatisfied. Message: Type .{0} does not satisfy constraint {1}
A type argument provided for a generic parameter does not meet the declared constraint.
<?tyhp
class Repository<T extends Entity> { }
// Error: 'string' does not satisfy constraint 'Entity'
Repository<string> $repo = new Repository<string>();
TYHP4036 (Error)CheckerGenericArgumentCountMismatch. Message: Generic type .{0} expects {1} type argument(s), found {2}
The number of generic type arguments does not match the number of generic type parameters declared.
<?tyhp
class Pair<TKey, TValue> { }
Pair<int> $p; // Error: expects 2 type arguments, but 1 was provided
TYHP4037 (Error)CheckerStructPropertyRequired. Message: All struct properties must be typed.
All properties in a struct declaration must have explicit type annotations.
TYHP4038 (Error)CheckerExtensionVisibilityNotAllowed. Message: Visibility adaptation is not allowed on extension members; extensions are always public.
A member inside an extension declaration attempts to adapt or restrict its visibility. Extension members are always public and cannot change visibility.
TYHP4039 (Error)CheckerThrowNotThrowable. Message: .throw expression must be an instance of \Throwable
A throw statement throws a value that does not implement \Throwable.
<?tyhp
throw "something went wrong";
// Error: Cannot throw value of type 'string': must be \Throwable
TYHP4040 (Error)CheckerCatchNotThrowable. Message: Caught type .{0} must implement \Throwable
A catch clause specifies a type that does not implement \Throwable.
TYHP4041 (Error)CheckerCatchNoIntersection. Message: Catch clause cannot use intersection types.
A catch clause uses an intersection type, which is not valid. Use union types (|) instead.
TYHP4042 (Error)CheckerCatchNoScalar. Message: Cannot catch scalar type .{0}
A catch clause specifies a scalar type like int or string.
TYHP4043 (Error)CheckerConditionNotBool. Message: Expected .bool, found {0}
The condition in an if, while, or ternary expression is not a boolean type.
TYHP4044 (Error)CheckerTraitRequirementNotMet. Message: Trait .{0} requires the using class to extend {1}
A trait declares a requirement that the using class must extend a specific base class, but the class does not.
TYHP4045 (Error)CheckerTraitRequirementImplNotMet. Message: Trait .{0} requires the using class to implement {1}
A trait declares a requirement that the using class must implement a specific interface, but the class does not.
TYHP4046 (Error)CheckerAsyncIterableMissingAwait. Message: Cannot iterate .AsyncIterable<{0}> synchronously; use foreach (await $expr as ...) inside an async function
A regular foreach is used on a value that implements AsyncIterable. Async iterables must be iterated with await foreach.
TYHP4047 (Error)CheckerAwaitNonAsyncIterable. Message: .await in foreach requires AsyncIterable<T> or Promise<Iterable<T>>, found {0}
The await foreach construct is used on a type that does not implement AsyncIterable.
TYHP4048 (Error)CheckerVoidInNonReturnPosition. Message: Type .void can only be used as a return type or in generic positions that explicitly allow it via constraint
The void type is used in a position other than a function/method return type, such as a generic type argument or parameter type.
<?tyhp
Collection<void> $items; // Error: 'void' can only be used as a return type
TYHP4049 (Error)CheckerNeverInNonReturnPosition. Message: Type .never can only be used as a return type or a generic type argument
never is a generic type argument (array<never>, PromiseInterface<never>) and a return type. It is still rejected as a parameter type, a property type, or a callable-shape parameter.
TYHP4050 (Error)CheckerUtilityTypeInvalidKey. Message: Key .{0} does not match a property on type {1}
A utility type such as Pick, Omit, or keyof was given a key that is not a known property on the target type.
Fix: Use a key that exists on the type, or adjust the type before selecting keys.
TYHP4051 (Error)CheckerUtilityTypeInvalidArgument. Message: Utility type argument does not satisfy constraint.
A type argument passed to a utility type does not meet that utility's constraints (for example, requiring an object type).
Fix: Pass a type that satisfies the utility's constraints.
TYHP4052 (Warning)CheckerReferenceTypeChanged. Message: Reference parameter .{0} reassigned to type {1}, which differs from declared type {2}
A by-reference parameter was reassigned to a value whose type differs from the parameter's declared type. Callers sharing that reference may observe an unexpected type.
Fix: Keep reference reassignments compatible with the declared parameter type.
TYHP4053 (Error)CheckerDuplicateTypeInComposite. Message: Type .{0} appears more than once in a union or intersection type
The same type appears more than once in a union or intersection (for example int|int or A&A).
Fix: Remove the duplicate member from the composite type.
TYHP4054 (Error)CheckerMixedInComposite. Message: .mixed or never cannot be used in union or intersection types
mixed and never cannot appear as members of a union or intersection because they absorb or contradict the other members.
Fix: Remove mixed/never from the composite, or replace the composite with mixed / never alone when that is the intended type.
TYHP4055 (Error)CheckerRedundantTypeInUnion. Message: Redundant type .{0} in union type
A union member is redundant because a wider member of the same union already covers it, so removing it does not change the set of values. Typical cases are bool|false, object|User, and iterable|array.
This is different from a duplicated member (int|int), which is TYHP4053.
<?tyhp
bool|false $flag;
object|User $entity;
Fix: Remove the redundant member from the union.
TYHP4056 (Error)CheckerUseBoolInsteadOfTrueFalse. Message: Use .bool instead of true|false
The union true|false is exactly the bool type. Spell it as bool instead of listing both boolean literals.
Fix: Replace true|false with bool.
TYHP4057 (Error)CheckerNonClassInIntersection. Message: Non-class type .{0} cannot appear in intersection types
Intersection types (A&B) may only contain class-like members (classes, interfaces, and similar). A non-class type such as a scalar or array cannot appear in an intersection.
Fix: Use a union (|) when mixing scalars with objects, or drop the non-class member.
TYHP4058 (Error)CheckerCallableNotAllowedOnProperty. Message: .callable cannot be used as a property type declaration
A property (including a promoted constructor parameter) cannot be declared with the callable type. PHP does not allow callable on properties.
Fix: Use \Closure, an interface, or a named class type instead of callable.
TYHP4059 (Error)CheckerVoidNotAllowedHere. Message: .void can only be used as a return type
void is only valid as a function or method return type. It cannot be used as a parameter type or property type (see also TYHP4048 for void as a generic type argument).
Fix: Use a different type, or mixed when "no value" is intended.
TYHP4060 (Warning)CheckerVoidRefReturn. Message: Returning by reference from a .void function is deprecated
A function or method declared void uses a by-reference return (function &foo(): void). Returning by reference from a void function is deprecated in PHP.
Fix: Drop the & or give the function a non-void return type.
TYHP4061 (Error)CheckerNeverNotAllowedHere. Message: .never can only be used as a return type
never is rejected as a parameter type or a property type. It is a valid generic type argument and a valid return type.
Fix: Use a different type for parameters and properties.
TYHP4062 (Error)CheckerResourceNotAllowed. Message: .resource cannot be used in user type declarations
resource is a historical PHP runtime type and cannot be written in user type declarations. Tyhp does not accept resource as a parameter, return, property, or alias type.
Fix: Use a class or interface that wraps the resource, or mixed if the value is intentionally untyped.
TYHP4063 (Error)CheckerRefArgMustBeVariable. Message: By-reference argument must be a variable, not a literal or expression.
A by-reference parameter must be passed a variable (or a dereferenceable location such as an array element or object property). Literals and temporary expressions cannot be passed by reference.
Fix: Store the value in a variable and pass that variable.
TYHP4064 (Error)CheckerRelativeTypeOutsideClass. Message: .self or parent used outside class context
self and parent name the enclosing class or its parent. They are not valid outside a class, interface, trait, or enum body (for example in a file-level function).
Fix: Use a named type, or move the declaration into a class-like body.
TYHP4065 (Error)CheckerParentWithoutParent. Message: .parent used in class {0} that has no parent class
parent is used in a class that does not extend another class, so there is no parent type to resolve.
Fix: Add an extends clause, or replace parent with a named type or self.
TYHP4066 (Error)CheckerStaticNotReturnType. Message: .static cannot be used as a parameter or property type
static is a late-binding return type (and is allowed in locals, instanceof, and generic arguments). It cannot be used as a parameter type or a property type.
Fix: Use self, a named class, or a generic parameter instead of static on parameters and properties.
TYHP4067 (Error)CheckerDnfRedundantIntersection. Message: Redundant intersection in DNF type.
A DNF type is a union of intersections, such as (A&B)|(A&C). One of those intersections is redundant because another member already covers it — for example (A&B)|A, where A&B is implied by A.
Fix: Remove the redundant intersection from the DNF type.
TYHP4068 (Error)CheckerNeverMustNotReturn. Message: Function with .never return type must not contain a return statement
Run tyhp --explain TYHP4068 for the long-form explanation.
TYHP4069 (Error)CheckerCannotInstantiateNonClass. Message: Cannot instantiate non-class type .{0}
Run tyhp --explain TYHP4069 for the long-form explanation.
TYHP4070 (Error)CheckerCannotInstantiateTrait. Message: Cannot instantiate trait .{0}
Run tyhp --explain TYHP4070 for the long-form explanation.
TYHP4071 (Error)CheckerCannotInstantiateInterface. Message: Cannot instantiate interface .{0}
Run tyhp --explain TYHP4071 for the long-form explanation.
TYHP4072 (Error)CheckerCannotInstantiateEnum. Message: Cannot instantiate enum .{0}
Run tyhp --explain TYHP4072 for the long-form explanation.
TYHP4073 (Error)CheckerCloneNonObject. Message: .clone cannot be applied to non-object type {0}
Run tyhp --explain TYHP4073 for the long-form explanation.
TYHP4074 (Error)CheckerMagicMethodSignature. Message: Magic method .{0} has invalid signature: {1}
Run tyhp --explain TYHP4074 for the long-form explanation.
TYHP4075 (Error)CheckerDuplicateParameter. Message: Duplicate parameter name .${0}
Run tyhp --explain TYHP4075 for the long-form explanation.
TYHP4076 (Warning)CheckerRequiredAfterOptional. Message: Required parameter .${0} follows optional parameter
Run tyhp --explain TYHP4076 for the long-form explanation.
TYHP4077 (Error)CheckerVariadicNotLast. Message: Variadic parameter must be the last parameter.
Run tyhp --explain TYHP4077 for the long-form explanation.
TYHP4078 (Error)CheckerVariadicWithDefault. Message: Variadic parameter cannot have a default value.
Run tyhp --explain TYHP4078 for the long-form explanation.
TYHP4079 (Error)CheckerDuplicateNamedArgument. Message: Duplicate named argument .{0}
Run tyhp --explain TYHP4079 for the long-form explanation.
TYHP4080 (Error)CheckerPositionalAfterNamed. Message: Positional argument after named argument.
Run tyhp --explain TYHP4080 for the long-form explanation.
TYHP4081 (Error)CheckerUnknownNamedArgument. Message: Named argument .{0} does not match any parameter
Run tyhp --explain TYHP4081 for the long-form explanation.
TYHP4082 (Error)CheckerNamedAfterUnpack. Message: Named argument after argument unpacking.
Run tyhp --explain TYHP4082 for the long-form explanation.
TYHP4083 (Error)CheckerClosureUseUndefined. Message: Variable .${0} in closure use clause is not defined in the enclosing scope
Run tyhp --explain TYHP4083 for the long-form explanation.
TYHP4084 (Warning)CheckerClosureUseThis. Message: .use($this) is redundant in non-static closures
Run tyhp --explain TYHP4084 for the long-form explanation.
TYHP4085 (Error)CheckerStaticClosureThis. Message: Static closure cannot reference .$this
Run tyhp --explain TYHP4085 for the long-form explanation.
TYHP4086 (Error)CheckerYieldOutsideGenerator. Message: .yield can only be used inside a generator function
Run tyhp --explain TYHP4086 for the long-form explanation.
TYHP4087 (Error)CheckerGeneratorInvalidReturnType. Message: Generator function expected .{0}, found {1}
Run tyhp --explain TYHP4087 for the long-form explanation.
TYHP4088 (Error)CheckerYieldInFinally. Message: .yield inside a finally block is not allowed
Run tyhp --explain TYHP4088 for the long-form explanation.
TYHP4089 (Error)CheckerYieldFromNonIterable. Message: .yield from expression must be iterable or a Generator
Run tyhp --explain TYHP4089 for the long-form explanation.
TYHP4090 (Error)CheckerNonConstantExpression. Message: Non-constant expression in constant-required context.
Run tyhp --explain TYHP4090 for the long-form explanation.
TYHP4091 (Error)CheckerDivisionByZero. Message: Division by zero in constant expression.
Run tyhp --explain TYHP4091 for the long-form explanation.
TYHP4092 (Error)CheckerDuplicateArrayKey. Message: Duplicate array key .{0}
Run tyhp --explain TYHP4092 for the long-form explanation.
TYHP4093 (Error)CheckerInvalidArrayAccess. Message: Cannot use array access on type .{0}
Run tyhp --explain TYHP4093 for the long-form explanation.
TYHP4094 (Error)CheckerDestructuringNonArray. Message: Cannot destructure non-array type .{0}
Run tyhp --explain TYHP4094 for the long-form explanation.
TYHP4095 (Error)CheckerDestructuringSpread. Message: Spread operator in list/destructuring is not allowed.
Run tyhp --explain TYHP4095 for the long-form explanation.
TYHP4096 (Error)CheckerSpreadNonIterable. Message: Spread operator requires an iterable type, found .{0}
Run tyhp --explain TYHP4096 for the long-form explanation.
TYHP4097 (Error)CheckerThisInStaticContext. Message: .$this cannot be used in static context
Run tyhp --explain TYHP4097 for the long-form explanation.
TYHP4098 (Error)CheckerNonStaticCalledStatically. Message: Non-static method .{0} cannot be called statically
Run tyhp --explain TYHP4098 for the long-form explanation.
TYHP4099 (Warning)CheckerStaticCalledOnInstance. Message: Static method .{0} called on instance
Run tyhp --explain TYHP4099 for the long-form explanation.
TYHP4100 (Error)CheckerStaticOutsideClass. Message: .static:: used outside class context
Run tyhp --explain TYHP4100 for the long-form explanation.
TYHP4101 (Error)CheckerSymbolNameNotFound. Message: Symbol .{0} is not found for type {1}
Run tyhp --explain TYHP4101 for the long-form explanation.
TYHP4104 (Error)CheckerGotoProhibited. Message: .goto is prohibited in Tyhp
Run tyhp --explain TYHP4104 for the long-form explanation.
TYHP4105 (Error)CheckerPromotedPropertyNoType. Message: Promoted constructor property must have a type annotation.
Run tyhp --explain TYHP4105 for the long-form explanation.
TYHP4106 (Error)CheckerPromotedPropertyInAbstract. Message: Promoted properties are not allowed in abstract or interface constructors.
Run tyhp --explain TYHP4106 for the long-form explanation.
TYHP4107 (Error)CheckerPromotedVariadic. Message: Variadic parameter cannot be a promoted property.
Run tyhp --explain TYHP4107 for the long-form explanation.
TYHP4108 (Error)CheckerReadonlyClassMutableProperty. Message: Mutable property .{0} in readonly class
Run tyhp --explain TYHP4108 for the long-form explanation.
TYHP4109 (Error)CheckerReadonlyClassStaticProperty. Message: Static property in readonly class.
Run tyhp --explain TYHP4109 for the long-form explanation.
TYHP4110 (Error)CheckerEnumCaseMissingValue. Message: Backed enum case .{0} must have a value
Run tyhp --explain TYHP4110 for the long-form explanation.
TYHP4111 (Error)CheckerEnumCaseValueOnNonBacked. Message: Non-backed enum case .{0} must not have a value
Run tyhp --explain TYHP4111 for the long-form explanation.
TYHP4112 (Error)CheckerEnumCaseDuplicateValue. Message: Duplicate enum case value .{0}
Run tyhp --explain TYHP4112 for the long-form explanation.
TYHP4113 (Error)CheckerEnumPropertyNotAllowed. Message: Enums cannot have instance properties.
Run tyhp --explain TYHP4113 for the long-form explanation.
TYHP4114 (Error)CheckerInterfacePropertyInitializer. Message: Interface property cannot have an initializer.
Run tyhp --explain TYHP4114 for the long-form explanation.
TYHP4115 (Error)CheckerInterfacePropertyNotAllowed. Message: Interfaces cannot have instance property declarations.
Run tyhp --explain TYHP4115 for the long-form explanation.
TYHP4116 (Error)CheckerTraitConflict. Message: Unresolved trait method conflict for .{0}
Run tyhp --explain TYHP4116 for the long-form explanation.
TYHP4117 (Error)CheckerCircularTraitUse. Message: Circular trait use detected: {0}.
Run tyhp --explain TYHP4117 for the long-form explanation.
TYHP4118 (Error)CheckerOverloadSignatureIncompatible. Message: Overload signature is not compatible with implementation signature.
Run tyhp --explain TYHP4118 for the long-form explanation.
TYHP4119 (Warning)CheckerIncomparableTypes. Message: Comparing types .{0} and {1} has no meaningful comparison
Run tyhp --explain TYHP4119 for the long-form explanation.
TYHP4120 (Error)CheckerConcatNonStringable. Message: String concatenation with non-stringable type .{0}
Run tyhp --explain TYHP4120 for the long-form explanation.
TYHP4121 (Warning)CheckerEmptyCatch. Message: Empty .catch block silently swallows exceptions
An empty catch block has no statements, so the exception is swallowed with no handling. That is often accidental.
When swallowing is intentional, name the exception and discard it with (void) — the same discard used for unused #[\NoDiscard] returns. (void)$e is a statement, so the catch body is not empty, and it records that the value is unused on purpose. A comment-only body is still empty.
<?tyhp
try {
$rp = new \ReflectionProperty($class, $name);
} catch (\ReflectionException $e) {
(void)$e;
}
TYHP4122 (Error)CheckerReturnInFinally. Message: Returning from a .finally block is not allowed
Run tyhp --explain TYHP4122 for the long-form explanation.
TYHP4123 (Warning)CheckerBreakInFinally. Message: .break/continue in a finally block
Run tyhp --explain TYHP4123 for the long-form explanation.
TYHP4124 (Warning)CheckerDuplicateCatch. Message: Exception type .{0} is already caught by a previous catch clause
Run tyhp --explain TYHP4124 for the long-form explanation.
TYHP4125 (Warning)CheckerCatchOrderBroadFirst. Message: Catching parent exception .{0} before child makes subsequent catch unreachable
Run tyhp --explain TYHP4125 for the long-form explanation.
TYHP4126 (Error)CheckerNotAnAttributeClass. Message: Class .{0} is not declared as an attribute class
Run tyhp --explain TYHP4126 for the long-form explanation.
TYHP4127 (Error)CheckerAttributeTargetMismatch. Message: Attribute .{0} cannot be applied to {1}
The attribute is not valid on this kind of declaration. PHP Core attributes declare allowed targets (TARGET_METHOD, TARGET_PROPERTY, and so on); applying one elsewhere is a target mismatch.
#[\Override] on a property is a target mismatch when output.phpVersion is below 8.5 (properties become a legal target at 8.5). On 8.5 or later, a property that does not actually override uses TYHP4129 instead.
When output.phpVersion is 8.5 or later, #[\DelayedTargetValidation] on the same declaration skips this target check for PHP Core attributes on that declaration. Functional checks still run: #[\Override] that does not override is still TYHP4129, unused #[\NoDiscard] returns are still TYHP4165, and #[\Override] on __construct is still TYHP4339. Below 8.5 the skip is ignored.
TYHP4128 (Error)CheckerAttributeNotRepeatable. Message: Attribute .{0} is not repeatable
Run tyhp --explain TYHP4128 for the long-form explanation.
TYHP4129 (Error)CheckerOverrideNotOverriding. Message: .{0} has the #[Override] attribute but does not override a parent method or property
#[\Override] marks a method or (PHP 8.5 or later) a property as intended to replace a parent or interface member. This error means no same-name non-private ancestor or interface member exists.
On output.phpVersion below 8.5, #[\Override] on a property is a target mismatch (TYHP4127), not this code. #[\Override] on __construct is always TYHP4339, even when a parent constructor exists.
Trait method bodies are not checked here; PHP applies the attribute on the composing class.
TYHP4130 (Warning)CheckerUnusedImport. Message: Unused import .{0}
Run tyhp --explain TYHP4130 for the long-form explanation.
TYHP4131 (Warning)CheckerDuplicateImport. Message: Duplicate import .{0}
Run tyhp --explain TYHP4131 for the long-form explanation.
TYHP4132 (Error)CheckerConflictingImportAlias. Message: Conflicting import alias .{0}
Run tyhp --explain TYHP4132 for the long-form explanation.
TYHP4133 (Error)CheckerVariableVariableProhibited. Message: Variable variables (.$$var) are prohibited in Tyhp
Run tyhp --explain TYHP4133 for the long-form explanation.
TYHP4134 (Error)CheckerDynamicPropertyProhibited. Message: Dynamic property creation is prohibited.
Run tyhp --explain TYHP4134 for the long-form explanation.
TYHP4135 (Error)CheckerCompactProhibited. Message: .compact() is prohibited in Tyhp
Run tyhp --explain TYHP4135 for the long-form explanation.
TYHP4136 (Error)CheckerExtractProhibited. Message: .extract() is prohibited in Tyhp
Run tyhp --explain TYHP4136 for the long-form explanation.
TYHP4137 (Warning)CheckerGlobalVariableWarning. Message: .global $var usage; prefer dependency injection
Run tyhp --explain TYHP4137 for the long-form explanation.
TYHP4138 (Error)CheckerClosureParameterTypeRequired. Message: Cannot infer type for closure parameter .${0}; provide an explicit type annotation
Run tyhp --explain TYHP4138 for the long-form explanation.
TYHP4139 (Error)CheckerCloneWithReadonlyRequiresConfig. Message: Clone .with on readonly property {0} requires build.experimentalReadonlyCloneWith: true in tyhp.json for PHP < 8.5
Run tyhp --explain TYHP4139 for the long-form explanation.
TYHP4140 (Error)CheckerWithReadonlyFinalClass. Message: Cannot use .with on readonly properties of final class {0} on PHP < 8.5
Run tyhp --explain TYHP4140 for the long-form explanation.
TYHP4141 (Error)CheckerWithReadonlyInPlace. Message: Cannot modify readonly property .{0} with in-place with; use clone ... with or new ... with instead
Run tyhp --explain TYHP4141 for the long-form explanation.
TYHP4142 (Error)CheckerMissingArgument. Message: Missing required argument for parameter .${0} of {1}
Run tyhp --explain TYHP4142 for the long-form explanation.
TYHP4143 (Error)CheckerTooManyArguments. Message: Too many arguments passed to .{0}; expected at most {1}, found {2}
Run tyhp --explain TYHP4143 for the long-form explanation.
TYHP4144 (Error)CheckerTemplateStringUnknownEscape. Message: Unknown escape sequence .{0} in template string type
Run tyhp --explain TYHP4144 for the long-form explanation.
TYHP4145 (Error)CheckerTemplateStringInvalidQuantifierRange. Message: Invalid quantifier range .{0} in template string type
Run tyhp --explain TYHP4145 for the long-form explanation.
TYHP4146 (Error)CheckerTemplateStringMaxStatesExceeded. Message: Template string type comparison exceeds the complexity limit ({0} states).
Run tyhp --explain TYHP4146 for the long-form explanation.
TYHP4147 (Error)CheckerExtensionMissingExtends. Message: Extension .{0} must declare a header extends type or nested extends groups
Run tyhp --explain TYHP4147 for the long-form explanation.
TYHP4148 (Error)CheckerGenericTypeofInStaticContext. Message: .typeof({0}) is not available in a static member because {0} is bound per instance
Run tyhp --explain TYHP4148 for the long-form explanation.
TYHP4150 (Error)CheckerReservedGenericVariantSuffix. Message: .{0} ends with {1}, which is reserved for the generic variant the compiler emits
Run tyhp --explain TYHP4150 for the long-form explanation.
TYHP4151 (Error)CheckerGenericOverrideParameterMismatch. Message: .{0} overrides a generic method and must declare the same generic parameters {1}
Run tyhp --explain TYHP4151 for the long-form explanation.
TYHP4152 (Error)CheckerGenericDefaultInStaticContext. Message: .default({0}) is not available in a static member because {0} is bound per instance
Run tyhp --explain TYHP4152 for the long-form explanation.
TYHP4153 (Error)CheckerConstructorDestructorCannotReturnValue. Message: .{0} cannot return a value
Run tyhp --explain TYHP4153 for the long-form explanation.
TYHP4154 (Error)CheckerPropertyHookInvalidModifier. Message: Cannot use the .{0} modifier on a property hook
Run tyhp --explain TYHP4154 for the long-form explanation.
TYHP4155 (Error)CheckerHookedPropertyReadonly. Message: Hooked properties cannot be readonly.
Run tyhp --explain TYHP4155 for the long-form explanation.
TYHP4156 (Error)CheckerGenericInstanceofInStaticContext. Message: .instanceof {0} / is {0} is not available in a static member because {0} is bound per instance
Run tyhp --explain TYHP4156 for the long-form explanation.
TYHP4157 (Error)CheckerPropertyPossiblyUninitialized. Message: Typed property .${0} is possibly uninitialized here; declare ?T ${0} = null, add an initializer, or guard the read with ?? / isset
PHP throws "Typed property must not be accessed before initialization" when a typed property has no initializer, is not set by constructor property promotion, and has not been definitely assigned on every constructor path before it is read.
Prefer declaring the property as nullable with an explicit null default (?T $prop = null) when the code does not need to distinguish "no value" from "value is null". Otherwise assign it in the constructor on all paths, or guard the read with ?? / isset (which do not throw on uninitialized typed properties).
Assignment via a helper method called from the constructor does not count — only a direct $this->prop = … in the constructor body (or a declaration-level initializer / promoted parameter) is a guaranteed source.
TYHP4158 (Error)CheckerUnsetTypedPropertyWithoutAllowUnset. Message: Cannot .unset typed property ${0} without #[\Tyhp\AllowUnset]; prefer ?T ${0} = null, or add the attribute when distinguishing uninitialized from null is required
PHP's unset() on a typed property returns the slot to the uninitialized state, which defeats property-initialization analysis.
Prefer declaring the property as nullable with an explicit null default (?T $prop = null) when "no value" and null are the same. Only opt in with #[\Tyhp\AllowUnset] when code genuinely needs the uninitialized state; then every unguarded read may report TYHP4157, and unset itself clears definite-initialization within the method.
TYHP4159 (Error)CheckerStructRequiredPropertyNotSet. Message: Required struct property .{0} on {1} must be set via new ... with [...]
Struct properties that are non-nullable and have no default value are required. They cannot be omitted from construction — supply them with new StructName() with [prop => value, ...].
Nullable properties (and properties with defaults) remain optional at construction.
TYHP4160 (Error)CheckerMixedRequiresNarrowing. Message: Type .mixed must be narrowed before this use
mixed is Tyhp's strict top type: any value may be assigned to it, but it cannot be used in type-specific operations until narrowed.
Narrow with a type guard (instanceof / is, \is_string(), \is_int(), a user-defined $param is T guard, or a null check) before member access, calls, indexing, arithmetic, bitwise ops, string concatenation, or similar. Comparison and instanceof/is themselves are allowed so narrowing remains possible.
Assignment and return already reject passing mixed where a more specific type is required (TYHP4008 / TYHP4009 / TYHP4010).
TYHP4161 (Error)CheckerReservedPropertyHookMethodSuffix. Message: .{0} ends with {1}, which is reserved for property-hook polyfill methods the compiler emits
PHP < 8.4 property-hook lowering emits private methods named __get_<prop>__tyhpPropertyHook and __set_<prop>__tyhpPropertyHook, then passes them as first-class callables into PropertyAccessor registration.
A user declaration ending with __tyhpPropertyHook would collide with those generated symbols. Rename the declaration.
TYHP4162 (Error)CheckerPipeRhsNotCallable. Message: Right-hand side of .|> is not callable
The pipe operator (|>) passes the left-hand value as the sole argument to the right-hand callable. The RHS must be a Closure, first-class callable, callable/\Closure-typed value, or an object with __invoke.
Replace the RHS with a single-argument callable (for example strlen(...) or (fn($x) => …)).
TYHP4163 (Error)CheckerPipeRhsInvalidArity. Message: Right-hand side of .|> must accept exactly one argument
The pipe operator (|>) has invalid arity: PHP pipes the left-hand value as a single argument. Callables with more than one required parameter, or with zero parameters, cannot be used on the RHS.
Wrap multi-argument callees in a Closure or arrow function that supplies the extra arguments, e.g. (fn($x) => \str_replace('a', 'b', $x)).
TYHP4164 (Error)CheckerPipeRhsByRefParameter. Message: Right-hand side of .|> must not take parameter ${0} by reference
Piped values are temporaries, so callables whose first parameter is by-reference are rejected (for example \array_pop(...)).
Wrap the call in a Closure that takes the value by value and forwards a local variable by reference if mutation is required.
TYHP4165 (Warning)CheckerNoDiscardReturnUnused. Message: Return value of .{0} is marked #[\NoDiscard] and must be used or discarded with (void){1}
#[\NoDiscard] marks a function or method whose return value should be used. An unused return is TYHP4165. When $message is a string literal, that text is appended to the warning after a colon.
Use the return value (assignment, argument, condition, and so on), or cast with (void) to mark an intentional discard: (void)important();. Assignment to $_ also counts as a use.
The warning comes from the invoked declaration. Calling through an interface or abstract method does not warn, even if that declaration is marked. An override does not inherit the warning unless it is itself marked. A trait-imported method keeps the attribute.
Tyhp reports this even when output.phpVersion is below 8.5 (PHP's runtime warning is a no-op on older minors). The (void) cast is native on 8.5 or later and is omitted from emitted PHP below 8.5.
TYHP4166 (Error)CheckerFinalPropertyHookOverridden. Message: Cannot override final property hook .{0}::${1}::{2}()
PHP 8.4 rejects overriding a final property hook at class-declaration time, the same as overriding a final method. final get and final set are independent — only the hook marked final is sealed.
Remove the overriding hook from the child, or drop final from the ancestor hook if the override is intentional.
TYHP4167 (Error)CheckerByRefPropertyGetHookRequiresPhp84. Message: By-ref property hook .&get requires PHP 8.4 or later; target is {0}
PHP 8.4 native property hooks support &get so $ref = &$obj->prop (and array-element writes that rely on by-ref get) can alias backing storage.
When output.phpVersion is below 8.4, Tyhp lowers hooks through magic __get, which cannot return by reference. Emitting an ordinary by-value get would silently change program semantics, so Tyhp reports an error instead.
Raise output.phpVersion to 8.4 or later to keep native &get, or rewrite the property to a by-value get hook if by-ref aliasing is not required.
TYHP4168 (Error)CheckerParameterizedStaticForbidden. Message: Parameterized .static<...> is not allowed; use bare static, self<...>, parent<...>, or an explicit class name
Tyhp forbids parameterized static<...> in every scope, including final classes.
Late-static binding names the late-bound class; it does not invent or rebind generic type arguments. Type arguments come from the call-site class spelling (Child<string>::factory()) or from the receiver/$this instantiation for instance methods.
Use: - bare static for fluent / LSB returns that should follow the late-bound class - self<...> or the declaring class name for factories that stamp method generics onto the class (e.g. _async<T>(...): self<T>) - parent<...> when an explicit parent instantiation is required
final class Promise<TReturn extends void|mixed = void> {
public static function _async<T extends void|mixed>(callable(): T $fn): self<T> { /* ... */ }
public function then<TResult>(callable(TReturn): TResult $cb): static { /* ... */ }
}
TYHP4169 (Warning)CheckerRedundantGlobalImport. Message: Local .use of {0} is redundant; it is already in scope via global use
Run tyhp --explain TYHP4169 for the long-form explanation.
TYHP4170 (Error)CheckerExtensionOperatorRenameForbidden. Message: Cannot rename operator .{0} with as; use hide or insteadof
Run tyhp --explain TYHP4170 for the long-form explanation.
TYHP4171 (Error)CheckerReservedExtensionBackerSuffix. Message: Type name .{0} collides with the reserved extension backer suffix {1}
Run tyhp --explain TYHP4171 for the long-form explanation.
TYHP4172 (Error)CheckerEmptyExtension. Message: Extension .{0} must declare at least one member
Run tyhp --explain TYHP4172 for the long-form explanation.
TYHP4173 (Error)CheckerExtensionHideUnknownMember. Message: Extension member .{0} does not exist and cannot be hidden
Run tyhp --explain TYHP4173 for the long-form explanation.
TYHP4174 (Error)CheckerInlineParameterMutation. Message: Spliced member .{0} writes a parameter that is not declared &, declares & on a parameter it does not write, or mutates $this without &
A spliced extension member substitutes the caller's argument where the parameter stood. A parameter the expression writes (assignment, compound assignment, ++ / -- in either position, or passing to a callee's & parameter) must be declared &, and only those parameters may be. Write a non-mutating increment as $v + 1. Writing $this without the &$this receiver annotation is TYHP4369; annotating &$this on a member that never writes $this is TYHP4370.
TYHP4175 (Error)CheckerInlineCycle. Message: Spliced member .{0} refers to itself, directly or through other spliced members
Reducing a spliced call must terminate. A member whose expression (after substituting other spliced members) refers back to itself would loop. Break the cycle or move the logic into a multi-statement member that Tyhp calls rather than splices.
TYHP4176 (Error)CheckerInlineAttributeOnExtensionMember. Message: .#[\Tyhp\Optimize\Inline] is not allowed on an extension member
Extension splicing is decided by the member's form (=> vs brace body), not by #[\Tyhp\Optimize\Inline]. Remove the attribute. On a Tyhp extension { } member, pick the form that matches whether PHP should keep a method.
TYHP4177 (Error)CheckerReservedInlineTempPrefix. Message: Variable .${0} collides with the reserved inline temporary prefix {1}
The compiler introduces locals named $__tyhpInlineTemp1, $__tyhpInlineTemp2, … when a spliced parameter is used more than once. Do not declare a variable whose name starts with that prefix.
TYHP4179 (Error)CheckerInlineInaccessibleMember. Message: Spliced member .{0} references {1}, which is less accessible than the member
A spliced expression is evaluated at the call site, not inside the declaring class. The body may only reference members at least as accessible as the spliced member itself: a public member's body may reference public members only; a protected body may reference protected and public; a private body may reference any member of the declaring class.
TYHP4180 (Error)CheckerNonReferenceableByRefArgument. Message: Argument for by-reference parameter .${0} is not referenceable
A & parameter requires an argument PHP can bind as a reference. The receiver of a member annotated &$this is that argument. Literals, constants, call results, readonly properties, and properties whose read path is by value ({ get; } in tyhpdef, __get, or offsetGet) are not referenceable. A tyhpdef { &get; } is. Pass a variable, a non-readonly stored property, or a { &get; } / &__get / &offsetGet path instead.
TYHP4181 (Error)CheckerErasedMemberUnsafeSplice. Message: Call to erased member .{0} cannot be spliced faithfully
A short => Tyhp extension member and a tyhpdef thin mapping have no PHP method. If the call site cannot be spliced without dropping an argument, delaying it, reordering side effects, or needing a reference-bound local with no statement slot, the compiler reports this error. Bind the argument to a variable first, or (on a Tyhp extension { } member) switch to a single-return brace body so a PHP method exists to call.
TYHP4182 (Error)CheckerUndefinedFunction. Message: Function .{0} is not found
A function call whose name does not resolve to any declared function, tyhpdef stub, use function import, or compile-time builtin is undefined. The binder does not bind call-site function names; the checker resolves them from the enclosing namespace, imports, and the global table. A PHP-version gate (declare(php=…) / #[\Tyhp\Php]) that is inactive for output.phpVersion omits the symbol, so a call outside that gate is the same error. Declare the function, import it, raise the compile target, or fix the name.
TYHP4183 (Error)CheckerCallableEllipsisNotAllowed. Message: .... is not a type argument; write callable(...): TReturn for unknown arity
Bare ... in a type-argument list is not a rest pack and not a trailing T.... Unknown-arity callables are written callable(...): bool as a generic bound (T extends callable(...): bool). ... is not valid on array, \Closure, or user generics, and is not a call-site type argument (identity<...>(1)).
TYHP4184 (Error)CheckerCallableAnyArityNotAValueType. Message: .callable(...): {0} cannot be used as a parameter, property, or return type; write T extends callable(...): {0} and use T
callable(...): TReturn pins a callback return type without pinning arity. The parameter list is unknown, so the facet is not a value type and is not invokable. Constrain a type parameter (TCallable extends callable(...): bool) and take TCallable $callback so inference can recover a concrete callable.
TYHP4185 (Error)CheckerCallableAnyArityNotInvokable. Message: Cannot call a value of type .{0}; any-arity callable(...): TReturn is not invokable
A value typed as callable(...): TReturn has an unknown parameter list, so a call cannot be checked. Pass the value, store it, or recover a concrete callable via TCallable extends callable(...): TReturn and inference. Direct callable(...): TReturn $cb parameters are also rejected (TYHP4184).
TYHP4186 (Error)CheckerTypeAliasFactoryTypeArguments. Message: Type alias factory .{0} cannot be called with type arguments; write typeof({0}<…>) or {0}(typeof(…))
A type alias factory is a PHP function over \Tyhp\Type values, not a generic function. Optional<int>() mixes type-argument syntax into a value call. Write typeof(Optional<int>) to get a Type value from a type, or Optional(typeof(int)) / Optional() to call the factory with \Tyhp\Type arguments.
TYHP4187 (Error)CheckerCallablePackEllipsisNotAllowed. Message: A parameter pack cannot take postfix .... as a type argument; write callable(__CallableParametersRest<T> ...): R
__CallableParametersRest<T> is a pack. On a callable shape it is an ordinary parameter (callable(Rest<T> ...$args): R) that splices T's parameters. Postfix T... as a generic type argument is not a splice marker.
TYHP4188 (Error)CheckerCallablePostfixEllipsisNotAllowed. Message: Postfix .T... is not a type argument; write callable(T ...$args): R for a homogeneous variadic
callable(T ...$args): R spells a trailing PHP variadic on a callable shape. Postfix T... is not valid as a generic type argument on array, \Closure, or user generics. int... $x (ellipsis glued to the type) is not the PHP variadic int ...$x.
TYHP4189 (Error)CheckerCallableSliceOverlap. Message: .__CallableParametersSlice uses of {0} overlap at parameter index {1}
Slices of one TCallable on the same function must be disjoint. A non-variadic Slice<T, N> $x occupies index N; a variadic Slice<T, N> ...$xs occupies N and every later index. Two slices that cover the same index overlap. Split the range or drop the duplicate slice.
TYHP4190 (Error)CheckerCallableSliceHole. Message: .__CallableParametersSlice uses of {0} leave a hole at parameter index {1}
Slices of one TCallable must cover required parameters without holes, ordered by TStart. Slice<T, 0> $x followed by Slice<T, 2> ...$rest skips index 1. Add a slice for the missing index or start the rest slice at the next index.
TYHP4191 (Error)CheckerCallableSliceMinOnFixed. Message: .TMin is only valid on a variadic __CallableParametersSlice parameter
A non-variadic Slice<T, N> $x is exactly parameter N. TMin counts how many arguments a variadic slice must receive (Slice<T, 1, 1> ...$arrays). Do not write the third type argument on a fixed Slice.
TYHP4192 (Error)CheckerCallableSliceIndexNotIntLiteral. Message: .__CallableParametersSlice index {0} must be a non-negative int literal
TStart and TMin are non-negative integer literal types (0, 1, …), the same family as __IndexValueType<T, 0>. A general int, a negative literal, or a type parameter is not an index.
TYHP4193 (Error)CheckerFileLevelTypedConstNotAllowed. Message: File-level .const declarations cannot have a type annotation
PHP typed constants exist only on classes, interfaces, traits, and enums. Write const X = 1; at file scope, or move the constant onto a type. Tyhpdef file-level const int X; remains legal because those declarations describe PHP constants that may have no exact value.
TYHP4194 (Error)CheckerClassConstTypeRequired. Message: Class constant .{0} must have a type annotation
Every class-level const needs a type, or inherits it from the ancestor that first declared the same name. A child const X = 2; under const int X is still int.
TYHP4195 (Error)CheckerClassConstTypeMismatch. Message: Class constant .{0} type {1} must match inherited type {2}
Redeclaring a class constant cannot change its type. Omit the type to inherit it, or repeat the ancestor's type.
TYHP4196 (Error)CheckerForeachBindingTypeMismatch. Message: Foreach .{0} type {1} is not assignable to declared type {2}
A foreach type annotation is a compatibility check, not a narrowing. The iterated key or value type must be assignable to the declared type; the loop variable then has that declared type.
TYHP4197 (Error)CheckerUnresolvedReceiver. Message: Cannot access a member, call a method, or index a value whose type could not be resolved.
When the checker cannot type a receiver, that expression is marked unresolved so a missing name does not cascade through assignability. Member access, method calls (including extension lookup), and indexing still require a resolved type and report TYHP4197.
This diagnostic is omitted when the receiver subtree already has an error (for example unknownFn()->x reports only the undefined function). Unnarrowed mixed uses TYHP4160, not this code. Assignability of unresolved values is unchanged.
TYHP4200 (Warning)CheckerUnusedVariable. Message: Variable .${0} is assigned but never read
Run tyhp --explain TYHP4200 for the long-form explanation.
TYHP4201 (Warning)CheckerUnusedParameter. Message: Parameter .${0} is never used
Run tyhp --explain TYHP4201 for the long-form explanation.
TYHP4202 (Warning)CheckerUnusedPrivateMember. Message: Private member .{0} is never referenced
Run tyhp --explain TYHP4202 for the long-form explanation.
TYHP4203 (Warning)CheckerAssignmentInCondition. Message: Assignment in condition; use .=== for comparison or add extra parentheses if intentional
Run tyhp --explain TYHP4203 for the long-form explanation.
TYHP4204 (Warning)CheckerConditionAlwaysTrueFalse. Message: Condition is always {0}.
Run tyhp --explain TYHP4204 for the long-form explanation.
TYHP4205 (Warning)CheckerRedundantCast. Message: Redundant cast to .{0}
Run tyhp --explain TYHP4205 for the long-form explanation.
TYHP4206 (Warning)CheckerDeadStore. Message: Value assigned to .${0} is overwritten before being read
Run tyhp --explain TYHP4206 for the long-form explanation.
TYHP4207 (Warning)CheckerUnnecessaryNullCheck. Message: Unnecessary null check on non-nullable type .{0}
Run tyhp --explain TYHP4207 for the long-form explanation.
TYHP4208 (Warning)CheckerUnreachableArm. Message: Unreachable match/switch arm.
Run tyhp --explain TYHP4208 for the long-form explanation.
TYHP4209 (Warning)CheckerLossyCast. Message: Lossy cast from .{0} to {1}
Run tyhp --explain TYHP4209 for the long-form explanation.
TYHP4210 (Info)CheckerErrorThresholdReached. Message: Error threshold reached for this file; further errors are suppressed.
Run tyhp --explain TYHP4210 for the long-form explanation.
TYHP4211 (Warning)CheckerStaticReturnSelfInNonFinal. Message: Returning .new self() from a method with return type static in non-final class {0}; child classes will receive parent instance
Run tyhp --explain TYHP4211 for the long-form explanation.
TYHP4212 (Warning)CheckerDisposableCircularReference. Message: Disposable scope has unresolvable circular references; disposal uses .try/finally instead of DisposableScope
Run tyhp --explain TYHP4212 for the long-form explanation.
TYHP4213 (Error)CheckerExistenceGateInvalidName. Message: Declaration existence gate must check for .{0} (fully-qualified name or __NAMESPACE__.'\Name')
Run tyhp --explain TYHP4213 for the long-form explanation.
TYHP4300 (Error)CheckerPhpVersionInvalidConstraint. Message: Invalid PHP version constraint .{0}
The string given to declare(php=…) or #[\Tyhp\Php] is not a valid Composer PHP version constraint.
<?tyhp
declare(php="eight-four");
function demo(): void {}
Use Composer constraint syntax such as >=8.4, ^8.2, 8.2.*, or >=8.2 <8.4. A bare "8.2" means the whole 8.2.* minor.
TYHP4301 (Error)CheckerPhpVersionDeclareNotAlone. Message: .declare(php=...) must not be combined with other declare directives
The php version-gate directive must appear alone in its declare statement. Mixing it with strict_types, output_file, or any other key is rejected.
<?tyhp
declare(strict_types=1);
declare(php=">=8.4");
Write two consecutive declare statements instead of combining keys. Consecutive declares are valid.
TYHP4302 (Error)CheckerPhpVersionUnreachable. Message: Unreachable under PHP version constraint .{0}
A nested PHP version constraint can never be true given its enclosing constraint, so the inner region is unreachable.
<?tyhp
declare(php=">=8.4") {
function outer(): void {}
declare(php="<8.3") {
function never(): void {}
}
}
This error applies only to nested gates. Sibling declare(php=…) blocks that cover different PHP versions are alternate variants, not unreachable code. An inactive file-level declare(php="…"); skips the file silently and does not report this error.
TYHP4303 (Error)CheckerPhpVersionDuplicateDeclaration. Message: Duplicate declaration of .{0} with overlapping PHP version constraints
Duplicate declarations of the same symbol have overlapping PHP version constraints. Two variants of a name are allowed when their effective constraints are pairwise disjoint, or when they are distinct function or method overloads (different parameter lists) under the same or overlapping gates.
<?tyhp
#[\Tyhp\Php(">=8.3")]
function example(): void {}
#[\Tyhp\Php(">=8.4")]
function example(): void {}
Those two constraints both match PHP 8.4 and later. Use disjoint ranges such as >=8.4 with <8.4 when you need version-specific declarations of the same name and signature.
TYHP4304 (Error)CheckerPhpVersionAttributeInvalidTarget. Message: .#[\Tyhp\Php] is not allowed on struct or extension declarations; wrap with declare(php=...) instead
#[\Tyhp\Php] is not a valid attribute target on a struct or on a Tyhp or tyhpdef extension declaration. Gate those forms with declare(php=…) instead.
<?tyhp
declare(php=">=8.4") {
extension GatedStringOps {
function gated_tag(extends string $this): string {
return \strtoupper($this);
}
}
}
The attribute remains legal on class, interface, enum, trait, their members, functions, and other ordinary attribute targets. File-level declare(php="…"); also gates the rest of that file.
TYHP4305 (Error)CheckerPhpVersionAttributeInvalidArgument. Message: .#[\Tyhp\Php] requires a string version argument
#[\Tyhp\Php] requires a string version argument, either positional or named. Omitting it, or passing a non-string, is rejected.
<?tyhp
#[\Tyhp\Php(">=8.4")]
function array_find(array $array, callable $callback): mixed {
return null;
}
#[\Tyhp\Php(version: ">=8.2 <8.4")]
function example(string $v): mixed {
return $v;
}
On a tyhpdef hooked property, place #[\Tyhp\Php] on the property, not on get or set.
TYHP4306 (Warning)CheckerPhpVersionDefaulted. Message: .output.phpVersion is unset; defaulting to 8.2
The compile target was defaulted to "8.2" because no project phpVersion was set, and this warning is emitted once per compilation.
Set output.phpVersion in tyhp.json to an explicit "8.0"–"8.5" value to choose the check and emit target and which version-gated declarations are visible. This diagnostic fires once per compilation, not once per file. An explicit but unsupported value is a different diagnostic and falls back to "8.4".
TYHP4307 (Error)CheckerExternTypeUsed. Message: Name .{0} is extern
A .tyhp file named or received an extern name. That name is a tyhpdef placeholder for a type, function, or const the current tyhpdef mentions but does not own, so it is not usable in Tyhp source.
<?tyhp
function f(\Elastica\Client $client): void {}
\bcadd("1", "2");
int $mode = \GMP_ROUND_PLUSINF;
The primary span is the use: a type annotation, new, instanceof, catch, a use / use function / use const import of that fully-qualified name, a generic argument, a union or intersection arm, a call of an extern function, a const fetch, or an expression whose inferred type is extern (including a call whose return or parameter type is extern). A secondary span labeled "declared here" points at the extern declaration.
When the declaration has // @provided-by: tyhpdef/ruflin-elastica or // @provided-by: tyhpdef/php-ext-bcmath, help cites that wrapper name as-is. Include that package so a real declaration replaces the placeholder.
Naming a real class whose signature mentions an extern type is not itself a use. Tyhpdef signatures and mapping bodies may name an extern function or const.
TYHP4310 (Error)CheckerGenericDefaultDoesNotSatisfyConstraint. Message: Default type .{0} does not satisfy constraint {1} on generic parameter {2}
Run tyhp --explain TYHP4310 for the long-form explanation.
TYHP4311 (Error)CheckerGenericNonDefaultAfterDefault. Message: Generic parameter .{0} without a default cannot follow parameter {1} which has a default
Run tyhp --explain TYHP4311 for the long-form explanation.
TYHP4312 (Error)CheckerGenericDefaultCircularReference. Message: Generic parameter .{0} has a circular default type reference
Run tyhp --explain TYHP4312 for the long-form explanation.
TYHP4320 (Error)CheckerPropertyPathRequiresInlineFn. Message: Parameter of type .PropertyPath<callable({0}): {1}> requires an inline fn expression (e.g., fn ($x) => $x->property)
A value that is not an inline fn was passed where PropertyPath<callable(TSource $source): TReturn> is expected. The compiler reads the property chain out of the arrow function at compile time, so an already-built closure carries no chain it can lower.
<?tyhp
function takes(\Tyhp\PropertyPath<callable(User $u): string> $path): void {}
takes($someClosure);
Pass an inline arrow function instead — takes(fn ($u) => $u->name). Forwarding an existing PropertyPath value (for example a parameter of the same type) is also accepted.
TYHP4321 (Error)CheckerPropertyPathInvalidBody. Message: PropertyPath expression must be a simple property access chain (e.g., fn ($x) => $x->prop->subProp).
The inline fn body is not a simple property-access chain rooted at the lambda parameter. Method calls, operators, function wrappers, and roots other than the parameter cannot be represented as a property path.
<?tyhp
function takes(\Tyhp\PropertyPath<callable(User $u): string> $path): void {}
takes(fn ($u) => \strtolower($u->name));
Use only -> or ?-> property accesses starting at the parameter — takes(fn ($u) => $u->address->city).
TYHP4322 (Error)CheckerExpressionUnsupportedNode. Message: Expression trees do not support .{0} expressions; simplify the fn body
The inline fn body contains an expression kind that cannot be represented in an expression tree. Assignments, await, yield, match, instanceof/is, nested fn/closures, free function calls, throw, and similar constructs are rejected so the emitted tree stays a faithful, inspectable data structure.
<?tyhp
function takes(\Tyhp\Expression<callable(User $u): bool> $pred): void {}
takes(fn ($u) => await $u->load());
Simplify the body to supported forms: property/method access, operators, casts, ternary/??, array access, new, literals, and definitely-assigned captures.
TYHP4323 (Error)CheckerExpressionRequiresInlineFn. Message: Parameter of type .Expression<callable({0}): {1}> requires an inline fn expression
A value that is not an inline fn was passed where Expression<callable(T $arg): R> is expected. The compiler builds the expression tree from the arrow function at compile time, so an already-built closure carries no tree it can lower.
<?tyhp
function takes(\Tyhp\Expression<callable(User $u): bool> $pred): void {}
takes($someClosure);
Pass an inline arrow function instead — takes(fn ($u) => $u->age > 18). Forwarding an existing Expression value (for example a parameter of the same type) is also accepted.
TYHP4324 (Error)CheckerExpressionCapturedVarUndefined. Message: Captured variable .${0} in expression tree must be definitely assigned
A variable from the enclosing scope is referenced inside an expression-tree fn, so it becomes a ConstantExpression capture. That variable must be definitely assigned at the construction site; reading an uninitialized local would produce an undefined runtime value in the tree.
<?tyhp
function takes(\Tyhp\Expression<callable(User $u): bool> $pred): void {}
function demo(): void {
int $minAge;
takes(fn ($u) => $u->age > $minAge);
}
Assign the captured variable before constructing the expression — $minAge = 18; then takes(fn ($u) => $u->age > $minAge).
TYHP4325 (Error)CheckerStructRequiredKeyMissing. Message: Required struct property .{0} is missing from {1}
A required field of a callable-parameter bag (__CallableParametersStruct / __CallableParametersTuple) is missing from the array literal. Parameters without defaults are required struct keys; parameters with defaults are optional keys and may be omitted.
<?tyhp
function apply<TCallable extends callable>(
TCallable $cb,
__CallableParametersStruct<TCallable> $args
): __CallableReturnType<TCallable> {
return $cb();
}
function greet(string $name, int $age = 0): string {
return $name;
}
function demo(): void {
apply(greet(...), ['name' => 'Ada']);
apply(greet(...), []);
}
The first call is valid ($age has a default). The second is not — $name is required. Optionality is modeled as required-key assignability on one struct, not an intersection of every key-subset bag.
TYHP4326 (Error)CheckerTraversableCannotBeListed. Message: .{0} cannot list \Traversable; use \Iterator or \IteratorAggregate
\Traversable is an engine interface. Only \Iterator and \IteratorAggregate may extend it. Classes, enums, interfaces, and traits list \Iterator or \IteratorAggregate instead of \Traversable. Listing both (for example implements \Iterator, \Traversable) is also rejected.
TYHP4327 (Error)CheckerPhpTypeInvalidTarget. Message: .#[\Tyhp\PhpType] is not allowed on {0}
#[\Tyhp\PhpType] replaces the emitted PHP type of a parameter, function or method return, property, or typed constant. It is not a valid target on a class, interface, trait, enum, enum case, catch type, local variable, or property hook. Put the attribute on the property or on the set parameter instead of on get/set.
TYHP4328 (Error)CheckerGeneratorSendIntersectionEmpty. Message: Generator .TSend intersection of {0} is empty
Each typed use of a yield expression (for example int $x = yield or foo(yield) when foo takes int) constrains generator TSend — the type of Generator::send(). Several such targets are intersected. If that intersection is empty (for example int vs string), no send value can satisfy every site. Untyped $x = yield does not constrain TSend (it stays mixed).
TYHP4329 (Error)CheckerPhpTypeInvalidSpelling. Message: .#[\Tyhp\PhpType] argument {0} is not a valid PHP type hint
#[\Tyhp\PhpType] takes a PHP type-hint spelling such as mixed, int, string|int, or ?\Foo. The constructor argument must be that string; invalid spelling (for example int[], ?mixed, or a missing argument) is a compile error. Checker types are unchanged; only the emitted PHP type uses the hint.
TYHP4330 (Error)CheckerArrayAccessKeyNotOffset. Message: .ArrayAccess key type {0} cannot be a struct or array
PHP array offsets cannot be arrays. Tyhp structs erase to arrays, so ArrayAccess<SomeStruct, TValue> is not a legal homogeneous map (that spelling is TKey plus default TValue, not a per-key shape). Use int, string, int|string, or an object key type. Per-key struct maps are ArrayAccessShape.
TYHP4331 (Error)CheckerArrayAccessShapeWideKey. Message: .ArrayAccessShape key type {0} is too wide; narrow or use as
An ArrayAccessShape index must be a struct-key literal (or a finite union of those keys). A wide string, int, or mixed key is not enough; narrow the key or assert it with as.
TYHP4332 (Error)CheckerArrayAccessShapeAppend. Message: .ArrayAccessShape does not allow append ($obj[] =)
ArrayAccessShape has a closed key set from TStruct. Append ($obj[] =) is only legal on homogeneous ArrayAccess. Write a known key such as $obj['host'] = ….
TYHP4333 (Error)CheckerArrayAccessShapeUnhandledKey. Message: .ArrayAccessShape key {0} is not covered by {1}
For each finite struct key K, offsetGet / offsetSet is checked with $offset assumed K. A key is covered only by a reachable value return (offsetGet) or a write of $value (offsetSet) of that field's type. throw and never do not cover an unhandled key; match is sufficient but not required.
TYHP4334 (Error)CheckerClosureBindIncompatible. Message: Cannot bind this closure to .{0}; expected {1}
After bindTo($x) or bindTo($x, 'static') the leftover TScope is unchanged. $newThis must still be an instance of that scope class (or of TThis when the stored scope is gradual). An explicit object $newScope requires TNewThis to be a subtype of that object's type; a string $newScope must be __SuperTypeName<TNewThis> (an ancestor name, not a descendant). call($newThis) is a temporary bind: $newThis must be a non-null object compatible the same way. Gradual TThis (object|null / bare \Closure) does not prove an error.
TYHP4335 (Error)CheckerClosureStaticScopeStored. Message: .'static' is not a stored closure TScope; it is only a bind / bindTo argument
The token 'static' on bind / bindTo means "keep the old stored TScope". It is not a class-name string and must not appear as a Closure type argument. Write \Closure<callable(…): mixed, TThis, TScope> with a real scope type, or omit TScope so the default __ClosureScope<TThis> is used.
TYHP4336 (Error)CheckerClosureNonRebindable. Message: This closure cannot be rebound.
PHP refuses to rebind some closures. Arrow functions, first-class callables, and fromCallable of a non-Closure cannot change $this or scope. Binding $newThis or $newScope to an internal (engine) class is also forbidden. A gradual \Closure annotation does not prove the value is non-rebindable.
TYHP4337 (Error)CheckerEngineEnumCannotBeListed. Message: .{0} cannot list {1}
\UnitEnum and \BackedEnum are engine interfaces. Classes, interfaces, and traits cannot implement or extend them. Enumerations are already \UnitEnum (and \BackedEnum when backed) and must not list those interfaces in implements. Only \BackedEnum may extend \UnitEnum.
TYHP4338 (Error)CheckerEnumEngineMethodRedeclared. Message: .{0} cannot redeclare {1}
The engine supplies cases on every enumeration and from / tryFrom on backed enumerations. Redeclaring those methods is an error.
TYHP4339 (Error)CheckerOverrideOnConstructor. Message: .#[Override] cannot be applied to __construct
PHP constructors are exempt from override signature checks, so #[Override] is invalid on __construct even when a parent constructor exists. This error is reported at every output.phpVersion. Use #[Override] on methods or (PHP 8.5 or later) properties that actually replace a parent or interface member. A method or property that does not override uses TYHP4129 instead.
TYHP4340 (Error)CheckerNativeTypeTestInvalidTarget. Message: .#[\Tyhp\NativeTypeTest] is not allowed on {0}
#[\Tyhp\NativeTypeTest] marks a free function or concrete static method as the native lowering for $x is T. Instance methods, abstract or interface methods, closures, and other declarations cannot be that lowering; emit is fqn($x) or \Class::method($x) with the guarded first parameter.
TYHP4341 (Error)CheckerNativeTypeTestRequiresTypeGuard. Message: .#[\Tyhp\NativeTypeTest] requires a type-guard return {0} is T on the first parameter
The attribute does not take a type argument. T is the type-guard return of the same function: the first parameter must be named in $param is T (not $other is T and not an index subject such as $array[$key] is T).
TYHP4342 (Error)CheckerNativeTypeTestTypeNotSingle. Message: .#[\Tyhp\NativeTypeTest] type {0} must be a single type; unions, intersections, and nullables are not allowed
T must be a single type after transparent alias expansion. Unions (int|string), intersections, and nullables (?string) stay on \Tyhp\Type::is at $x is … sites; mark a guard only when it tests one exact type (for example string, int, or a class name).
TYHP4343 (Error)CheckerNativeTypeTestExtraParamsNeedDefaults. Message: .#[\Tyhp\NativeTypeTest] extra parameters after the first must have default values
$x is T emits fqn($x) and does not pass further arguments. Extra parameters after the guarded first parameter must all have defaults (or be variadic) so a one-argument call is valid.
TYHP4344 (Error)CheckerNativeTypeTestDuplicate. Message: .#[\Tyhp\NativeTypeTest] for {0} overlaps {1} registered by {2}
Only one callable may be the native test for a given T, including overlapping guarded types (for example string and int|float|string). Canonical PHP builtins such as is_int are marked; aliases such as is_integer / is_long stay callable but do not win $x is int. Concrete static methods are allowed; instance and abstract methods are not.
TYHP4345 (Error)CheckerEraseGenericInvalidTarget. Message: .#[\Tyhp\EraseGeneric] is not allowed on {0}
Run tyhp --explain TYHP4345 for the long-form explanation.
TYHP4346 (Warning)CheckerGenericRuntimeAuthorWritten. Message: .#[\Tyhp\GenericRuntime] is compiler-generated; this usage is overwritten at emit
Run tyhp --explain TYHP4346 for the long-form explanation.
TYHP4347 (Error)CheckerObjectShapeUsedAsClass. Message: Object shape .{0} is not a class
Run tyhp --explain TYHP4347 for the long-form explanation.
TYHP4348 (Error)CheckerObjectShapeNotTypeAlias. Message: .object { } is only allowed as the right-hand side of a type alias
Run tyhp --explain TYHP4348 for the long-form explanation.
TYHP4349 (Error)CheckerObjectShapeEmpty. Message: Empty object shape is not allowed; use .object
Run tyhp --explain TYHP4349 for the long-form explanation.
TYHP4350 (Error)CheckerObjectShapeNonPublicMember. Message: Object shape member .{0} must be public
Run tyhp --explain TYHP4350 for the long-form explanation.
TYHP4351 (Error)CheckerNewTypeArgumentNotObjectShape. Message: Type argument .{0} of __New must be an object-shape alias
Run tyhp --explain TYHP4351 for the long-form explanation.
TYHP4352 (Error)CheckerNewConstraintNotConstructable. Message: .{0} does not satisfy __New<{1}> because it is {2}
Run tyhp --explain TYHP4352 for the long-form explanation.
TYHP4353 (Error)CheckerNewConstraintNonPublicConstructor. Message: .{0} does not satisfy __New<{1}> because its constructor is not public
Run tyhp --explain TYHP4353 for the long-form explanation.
TYHP4354 (Error)CheckerNewConstraintConstructorMismatch. Message: .{0} does not satisfy __New<{1}> because its constructor is not compatible
Run tyhp --explain TYHP4354 for the long-form explanation.
TYHP4355 (Error)CheckerNewTypeParameterRequiresNew. Message: .new {0}() requires {0} to be __New<...>
Run tyhp --explain TYHP4355 for the long-form explanation.
TYHP4356 (Error)CheckerNewClassNameRequiresNew. Message: .new ${0}() requires __ClassName<__New<...>>, found {1}
Run tyhp --explain TYHP4356 for the long-form explanation.
TYHP4357 (Error)CheckerObjectShapeConstructorArgumentMismatch. Message: Constructor arguments for .{0} do not match object shape {1}
Run tyhp --explain TYHP4357 for the long-form explanation.
TYHP4358 (Error)CheckerObjectShapeRequiresGuard. Message: .{0} is not assignable to object shape {1} without a shape guard
Run tyhp --explain TYHP4358 for the long-form explanation.
TYHP4359 (Error)CheckerObjectShapeConstructNotCallable. Message: .__construct is not callable on a value of object shape {0}
Run tyhp --explain TYHP4359 for the long-form explanation.
TYHP4360 (Error)CheckerCallableShapeRequiresGuard. Message: .{0} is not assignable to callable shape {1} without a shape guard
Run tyhp --explain TYHP4360 for the long-form explanation.
TYHP4361 (Error)ParserExtensionLegacyMemberTarget. Message: Per-member .extends Type $this and operator op<Type> are not how an extension names its target. Use extension Name extends Type or a nested extends Type group
Writing extends Type $this on a member, or <Type> after an operator token, is the old per-member target spelling. Name the target on the block with extension Name extends Type or a nested extends Type group. Adaptation clauses in use extension still qualify an operator by target (E::operator +<Money>).
TYHP4362 (Error)CheckerExtensionHeaderAndNestedTargets. Message: Extension .{0} declares a header extends and a nested extends group
A header extends and nested extends groups are mutually exclusive. A header extends Type covers every member of the extension. Nested extends Type { } groups each name their own target in place of a header. Keep one header target, or move every member into a group.
TYHP4363 (Error)CheckerExtensionLooseMemberBesideGroup. Message: Extension .{0} declares a nested extends group and a member outside a group
An extension that uses nested extends groups puts every member inside a group. A member written beside those groups, outside any group, has no target. Move the member into a group, or remove the groups and use a header extends for the whole extension.
TYHP4364 (Error)CheckerExtensionTargetNotSingleType. Message: Expected a single named type, found .{0}
The block target is an intersection, void, never, mixed, a type parameter, an object { … } shape, _, or a union that contains one of those. A union whose members are each a legal target is valid, and so is ?T. An alias is read through to its body, so an alias of a legal union is a legal target.
TYHP4365 (Error)CheckerExtensionUnusedTypeParameter. Message: Type parameter .{0} is not used
A type parameter on extension Name<T> or on a nested extends<T> group is in scope for that block and must be referenced there: in the target, in a constraint or default, or in a member. A parameter that is never referenced is unused. Remove it, or use it.
TYHP4366 (Error)CheckerExtensionTypeParameterShadowed. Message: Type parameter .{0} shadows a type parameter on the enclosing extension
Type parameters on extension Name<T> or extends<T> stay on that symbol. They are in scope for the target and the members, and they are not copied onto each method. A method lists only the type parameters written on it. A method type parameter that reuses one of those names shadows the enclosing parameter. Give the method parameter a different name.
TYHP4367 (Error)CheckerExtensionOverlappingMember. Message: .{0} is declared on overlapping targets {1} and {2}
Two groups in one extension overlap when both can apply to the same receiver and both declare the same method or operator. extends string and extends string|int both apply to string. Different member names on overlapping targets are fine. Targets that do not overlap may share a method name. The same member on two separate extensions is an activation conflict, resolved with hide or insteadof on use extension.
TYHP4368 (Error)CheckerExtensionRelativeType. Message: .{0}:: is not allowed in an extension member
Inside an extension member, self and self:: name the block target, including a scalar target. static:: and parent:: are not the block target. Name the extension class by writing its name. An anonymous class nested in the member keeps its own self and static.
TYHP4369 (Error)CheckerExtensionByRefReceiverRequired. Message: Extension member .{0} writes $this without &$this
An extension member that writes $this needs the &$this receiver annotation. A write is an assignment, a compound assignment, ++ / --, or passing $this to a by-reference parameter. On a class, interface, or enum, assigning a property ($this->amount = 1) or calling a method does not write $this. On a scalar, array, or struct, assigning through $this ($this->field, $this[$k], or $this[]) does.
TYHP4370 (Error)CheckerExtensionByRefReceiverUnused. Message: Extension member .{0} declares &$this but does not write $this
&$this is the by-reference receiver annotation, and an extension member declares it only when the body writes $this. Reading $this, or mutating a property of a class, interface, or enum receiver, is not that write. Remove &$this, or write $this if the annotation was intentional. A missing annotation on a member that does write $this is TYHP4369.
TYHP4371 (Error)CheckerPhpVersionAttributeInvalidMember. Message: .#[\Tyhp\Php] is not allowed on {0}; declare a separate type per PHP version inside declare(php=...) instead
PHP cannot declare a property, class constant, enum case, or interface method conditionally, so #[\Tyhp\Php] on one of them has no PHP form to emit. When such a member differs between PHP versions, declare the whole class, interface, or enum once per version inside declare(php=…) blocks.
<?tyhp
declare(php="<8.3") {
class Limits {
const MAX = 10;
}
}
declare(php=">=8.3") {
class Limits {
const int MAX = 10;
}
}
#[\Tyhp\Php] stays legal on functions, classes, interfaces, traits, enums, and methods of classes, traits, and enums. Members of tyhpdef declarations may still carry it.
TYHP4372 (Error)CheckerReservedPhp86Name. Message: The name .{0} cannot be used as a {1}
Run tyhp --explain TYHP4372 for the long-form explanation.
TYHP4500 (Warning)CheckerDeprecatedUsage. Message: .{0} is deprecated{1}
A use of a deprecated symbol. The compiler sets deprecation from #[\Deprecated] on the declaration and from the tyhpdef deprecated keyword. Both produce this same warning (TYHP4500).
When #[\Deprecated] has a string-literal $message, that text is appended after a colon. $since is not part of the short message.
The symbol still compiles. Tyhp warns even when output.phpVersion is below 8.4 (PHP's runtime E_USER_DEPRECATED is a no-op on older minors). The class itself stays version-gated in tyhpdef/php.
TYHP4501 (Error)CheckerObsoleteUsage. Message: .{0} is obsolete and must not be used
Code references a symbol that has been marked as obsolete. This is stronger than deprecated and the symbol may be removed imminently.
TYHP4800 (Info)CheckerEvalUsage. Message: .eval() usage detected — this is disabled in Tyhp by default
The code uses eval(), which Tyhp disallows by default for security and type-safety reasons.
Fix: Replace eval() with a safer alternative. If eval() is absolutely necessary, enable it with build.allowEval: true in tyhp.json.
TYHP4801 (Error)CheckerIncludeNotAllowed. Message: .include/require is not allowed in Tyhp; use import instead
Tyhp does not allow include, require, include_once, or require_once statements. Use use/import statements and Composer autoloading instead.
TYHP4802 (Error)CheckerNestedNamedFunctionNotAllowed. Message: Named function or method .{0} cannot be declared inside another function or method; nested named declarations are not allowed in Tyhp
Run tyhp --explain TYHP4802 for the long-form explanation.
Emitter errors occur during PHP code generation.
TYHP5001 (Error)EmitterUnknownError. Message: Unknown emitter error: {0}.
A catch-all for unexpected errors during PHP code generation.
TYHP5002 (Error)EmitterUnsupportedAstNode. Message: Cannot emit AST node type .{0} — no emission handler implemented
The emitter encountered an AST node type that it does not know how to convert to PHP. This typically indicates a new language feature whose emitter support is not yet complete.
TYHP5003 (Error)EmitterOutputPathConflict. Message: Output path conflict: .{0} is targeted by multiple declarations
Two or more class/file declarations would produce output at the same file path.
Fix: Ensure each class has a unique fully-qualified name. If two classes share a name, place them in different namespaces.
TYHP5004 (Error)EmitterNamespaceMismatch. Message: Cannot merge output files: namespace mismatch (.{0} vs {1})
An attempt to merge two output files failed because they declare different namespaces.
TYHP5005 (Error)EmitterInvalidOutputPath. Message: Invalid output path: .{0} — {1}
The computed output path for a generated PHP file is invalid or inaccessible.
TYHP5006 (Warning)EmitterTypeErasureWarning. Message: Type .{0} is erased to mixed in PHP output
A Tyhp type could not be represented in PHP and was erased to mixed. This is informational -- the type checking was still performed at compile time.
TYHP5007 (Error)EmitterWriteError. Message: Failed to write output file .{0}: {1}
The emitter could not write a generated PHP file to disk due to a file system error.
TYHP5008 (Warning)EmitterTyhpConstructNotImplemented. Message: Tyhp construct .{0} is not yet supported by the emitter
A Tyhp-specific language feature does not yet have emitter support. The code compiles but the feature is not emitted.
TYHP5009 (Error)EmitterInvalidDeclareDirective. Message: Invalid declare directive: {0}.
A declare() statement contains an invalid or conflicting directive.
TYHP5010 (Warning)EmitterEmptyOutputFile. Message: Output file .{0} has no statements and will not be written
An output file was generated with no PHP statements (e.g., a source file contained only type aliases or struct declarations that are erased).
TYHP5011 (Warning)EmitterMergeConflict. Message: Conflicting declarations during merge of .{0}: {1}
Two output files being merged into one contain conflicting declarations.
TYHP5012 (Error)EmitterUnsupportedConstruct. Message: Tyhp construct .{0} cannot be emitted to PHP
An unsupported Tyhp construct cannot be lowered to PHP — it is not merely unimplemented yet (that is TYHP5008). The emitter has no valid PHP representation for the named construct.
Fix: Rewrite the code using a construct Tyhp can emit, or check whether a newer compiler adds support.
TYHP5013 (Error)EmitterNameConflict. Message: Generated method name .{0} conflicts with an existing method in {1}
A method name the emitter generated (for example a lowered hook, generic variant, or helper) conflicts with a method that already exists on the same class.
Fix: Rename the authored method so it does not clash with the generated name.
TYHP5014 (Error)EmitterMissingRuntime. Message: TyhpLib runtime is required but not configured for .{0}
The compiled output needs the TyhpLib runtime (the tyhp/core family of packages) for the named construct, but the project is not configured to include it.
Fix: Restore the runtime package reference (Composer tyhp/core / tyhp.json runtime settings) and rebuild.
TYHP5015 (Error)EmitterStructBackingError. Message: Configured struct backing class .{0} is not found
Run tyhp --explain TYHP5015 for the long-form explanation.
TYHP5016 (Error)EmitterDisposableError. Message: Disposable variable of type .{0} does not implement IsDisposable
Run tyhp --explain TYHP5016 for the long-form explanation.
TYHP5017 (Warning)EmitterAttributeStrippedForPhpVersion. Message: Attribute .{0} on {1} is stripped; target PHP {2} cannot represent it
PHP only allows attributes on certain constructs starting at specific versions. Top-level (non-class) const attributes require PHP 8.5+. Attributes on property hooks require native property hooks (PHP 8.4+); when hooks are lowered for an older output.phpVersion, those attributes cannot be preserved in a Reflection-compatible form.
Raise output.phpVersion, or remove the attribute if it is not needed at runtime.
TYHP5018 (Error)EmitterInteropContractMismatch. Message: Runtime package .{0} interop contract version is {1}, expected {2}
Compiled Tyhp depends on concrete \Tyhp\* runtime shapes. Each runtime Composer package stamps extra.tyhp.interopContractVersion, which must match the compiler's InteropContract.CurrentVersion.
Upgrade or reinstall matching tyhp/core, tyhp/async, tyhp/decimal, and/or tyhp/lambda packages, or upgrade the Tyhp compiler so both sides share the same contract version. See the interop contract docs.
TYHP5019 (Error)EmitterPostfixOperatorOverloadRequiresStatementSplit. Message: Overloaded postfix .{0} cannot be statement-split in this expression; capture the prior value in a separate statement
Overloaded ++ / -- rewrites to a method call plus write-back. Postfix forms must yield the value from before that write-back, which the emitter does by splitting into preceding statements ($__old = $a; $a = Type::__increment($a); … $__old).
That split is not safe inside short-circuit operands (&&, ||, ??), ternary arms, else if conditions (reached only when earlier conditions in the chain were false), or loop conditions that re-evaluate each iteration. Move the postfix into its own statement (or use prefix ++$a when the new value is intended), then use the captured variable in the expression.
TYHP5020 (Warning)EmitterSourceMapGenerationFailed. Message: Failed to generate source map for file .{0}: {1}
Source map generation builds Source Map v3 JSON from mappings collected while emitting PHP. A failure here is non-fatal: the .php file is still written, but debugging and stack-trace mapping for that file will not have a .map companion.
The build continues. Inspect the detail in the warning for the underlying exception, then retry with build.generateSourcemap enabled after fixing the cause.
TYHP5021 (Warning)EmitterSourceMapWriteFailed. Message: Failed to write source map file .{0}: {1}
The compiler writes a .php.map file next to each generated PHP file when build.generateSourcemap is true. A write failure (permissions, disk full, invalid path) is non-fatal: the PHP output is still usable without the map.
The build continues. Fix the path or permissions named in the warning and rebuild to produce the missing source map file.
TYHP5022 (Warning)EmitterSourceMapInvalidMapping. Message: Invalid source mapping in file .{0}: generated position ({1},{2}) references invalid source position ({3},{4})
A source mapping segment points at a generated PHP position whose original .tyhp line or column is invalid (negative, or otherwise not a real start position). The mapping is skipped; remaining segments are still emitted.
This is non-fatal. If mappings look wrong in a debugger, report the generated and original coordinates from this warning — they identify the emit item whose AST provider had a bad span.
TYHP5023 (Error)EmitterGenericRuntimeLayoutUnsupported. Message: .#[\Tyhp\GenericRuntime] layouts {0} have no intersection with this compiler{1}
Run tyhp --explain TYHP5023 for the long-form explanation.
Configuration errors are reported when tyhp.json or CLI options are invalid.
TYHP6001 (Error)ConfigUnknownError. Message: Configuration error.
A generic configuration error that does not match a more specific code.
TYHP6002 (Error)ConfigMissingRequiredField. Message: Required configuration field is missing.
A required field in tyhp.json is not present.
TYHP6003 (Warning)ConfigInvalidValue. Message: Invalid configuration value for .{0}: {1}
A configuration value is out of range, the wrong type, or otherwise invalid.
TYHP6004 (Error)ConfigInvalidGlobPattern. Message: Invalid glob pattern in configuration.
An include or exclude glob pattern in tyhp.json is malformed.
TYHP6005 (Error)ConfigOutputPathNotWritable. Message: Output path is not writable.
The configured output directory does not exist and cannot be created, or the process does not have write permissions.
TYHP6006 (Warning)ConfigInvalidPhpVersion. Message: Unsupported PHP version .{0}; using default 8.4
The output.phpVersion configuration specifies a PHP version that is not recognized or supported.
TYHP6007 (Error)ConfigPsr4InvalidMapping. Message: Invalid PSR-4 mapping in configuration.
A psr4 configuration entry maps a namespace to a path that is invalid or does not exist.
TYHP6008 (Warning)ConfigInvalidProjectType. Message: Unrecognized project type .{0}; using application
Run tyhp --explain TYHP6008 for the long-form explanation.
TYHP6009 (Error)ConfigInterpolationFailed. Message: Cannot expand .{0} in {1}: {2}
A placeholder in tyhp.json could not be expanded during interpolation. Path keys such as output.path, output.publishPath, cache-dir, psr4 values, and output.publishContent src/dst/exclude support {name}-style variables.
{name} and {version} (and {projectVersion}) come from composer.json next to tyhp.json, not from a file build.updateComposer may write under output.publishPath. {version.suffix} is everything after the numeric patch and is empty when omitted. {type} is the tyhp.json project kind. {composer.type} is Composer's type. {phpVersion.id} is the Tyhp PHP id for output.phpVersion (8.2 → 802). {env.NAME} reads a process environment variable; it is an error if that variable is unset.
File variables ({fileName}, {fileStem}, {extension}, {recursiveDir}, {relativePath}) are only valid in output.publishContent dst, and expand after glob matching. {extension}, {fileStem}, and {recursiveDir} may be empty. Use {{ and }} for a literal brace. tyhp init does not write version into composer.json; add that field before using {version}.
CLI errors are reported by compiler actions (build, lint, init, and related commands).
TYHP7000 (Error)InstallUnknownTarget. Message: Unknown install target .{0}; known targets: {1}
Run tyhp --explain TYHP7000 for the long-form explanation.
TYHP7001 (Error)InstallPhpNotFound. Message: PHP is not found on PATH; the Composer installer requires PHP.
Run tyhp --explain TYHP7001 for the long-form explanation.
TYHP7002 (Error)InstallConflictingLocationFlags. Message: .--local and --global cannot be combined
Run tyhp --explain TYHP7002 for the long-form explanation.
TYHP7003 (Error)InstallComposerDownloadFailed. Message: Composer installer download failed: {0}.
Run tyhp --explain TYHP7003 for the long-form explanation.
TYHP7004 (Error)InstallComposerChecksumMismatch. Message: Composer installer SHA-384 does not match.
Run tyhp --explain TYHP7004 for the long-form explanation.
TYHP7005 (Error)InstallComposerSetupFailed. Message: Composer installer failed: {0}.
Run tyhp --explain TYHP7005 for the long-form explanation.
TYHP7006 (Error)InstallComposerNotFoundAfterInstall. Message: Composer binary is not found at .{0} after install
Run tyhp --explain TYHP7006 for the long-form explanation.
TYHP7100 (Error)BuildUnknownError. Message: Build failed.
A generic build action error.
TYHP7101 (Info)BuildNoSourceFiles. Message: No source files found matching include patterns.
The build action found no .tyhp or .php files matching the configured include patterns.
Fix: Check the include and exclude patterns in tyhp.json. Ensure your source files have the correct file extensions.
TYHP7102 (Error)BuildOutputPathConflict. Message: Output path conflict: multiple files write to .{0}
During the build, multiple output file declarations would write to the same output path on disk.
TYHP7103 (Error)BuildFileWriteError. Message: Failed to write output file .{0}: {1}
A generated PHP file could not be written to disk (write failed: disk full, permission denied, or similar).
TYHP7104 (Error)BuildCleanFailed. Message: Cannot clean output directory .{0}: {1}
The --clean flag or output.publishClean was used but the target directory could not be cleaned (e.g., safety check failed or permission denied). output.publishClean refuses to delete the project root.
TYHP7105 (Warning)BuildRuntimePackageNotAvailable. Message: Tyhp runtime Composer package .{0} is not available; compiled code may not run correctly without it
A Tyhp runtime Composer package (e.g., tyhp/core, tyhp/decimal, tyhp/async) is needed by the compiled output but could not be found or installed.
TYHP7106 (Error)BuildPublishContentFailed. Message: Failed to copy publish content .{0}: {1}
Copying extra files into the publish directory failed. Check that output.publishContent sources exist, destinations stay under output.publishPath, and the process can write there.
TYHP7107 (Warning)BuildPublishContentUnmatched. Message: Publish content src .{0} matched no files
An output.publishContent src pattern was unmatched: it matched no files. Set required to true if a missing match should fail the build.
TYHP7200 (Error)LintFileNotFound. Message: File not found: .{0}
The --file argument to tyhp lint specifies a file path that does not exist.
TYHP7201 (Error)LintPathNotFound. Message: Path .{0} does not exist
A positional path passed to tyhp lint does not exist on disk.
TYHP7202 (Error)LintInvalidPath. Message: Path .{0} is invalid: {1}
A positional path passed to tyhp lint could not be interpreted as a file or directory.
TYHP7203 (Error)LintAccessDenied. Message: Access denied: {0}.
Access was denied while reading a source file or directory during lint (permissions, sandbox, or similar).
TYHP7204 (Error)LintIoError. Message: I/O error: {0}.
An I/O failure occurred while discovering or reading source files.
TYHP7205 (Error)LintUnexpectedError. Message: Unexpected error ({0}): {1}.
An unexpected failure occurred during linting; the first placeholder identifies the failure category.
TYHP7206 (Warning, Info)LintNoSourceFiles. Message: No source files match the include/exclude paths in .tyhp.json
No source files matched. Reported as informational for an empty project include set, and as a warning when explicit paths resolve to nothing.
TYHP7207 (Error)LintCancelled. Message: Lint cancelled.
Linting was cancelled (for example Ctrl+C). Diagnostics collected up to that point are still reported.
TYHP7208 (Error)LintFileNotInProject. Message: File .{0} is not within the project source paths
The file specified with --file is not part of the configured project source paths.
TYHP7209 (Info)LintFixApplied. Message: Auto-fix applied: {0}.
An auto-fix was successfully applied to resolve a lint issue (when using tyhp lint --fix).
TYHP7210 (Warning)LintFixFailed. Message: Auto-fix .{0} could not be applied: {1}
An auto-fix was attempted but could not be applied. The placeholders name the fix and the reason (auto-fix implementations are still stubs, so this currently reports Not yet implemented).
TYHP7211 (Error)LintUnsupportedFormat. Message: Unsupported output format .{0}; valid formats: text, json, sarif
The --format argument to tyhp lint specifies a format that is not recognized.
TYHP7300 (Error)LspUnknownError. Message: Language server failed: {0}.
Run tyhp --explain TYHP7300 for the long-form explanation.
TYHP7301 (Error)LspServerStartupFailed. Message: Language server startup failed: {0}.
Run tyhp --explain TYHP7301 for the long-form explanation.
TYHP7302 (Error)LspAnalysisError. Message: Document analysis failed: {0}.
Run tyhp --explain TYHP7302 for the long-form explanation.
TYHP7303 (Error)LspSourceMapLoadError. Message: Sourcemap .{0} could not be loaded: {1}
Run tyhp --explain TYHP7303 for the long-form explanation.
TYHP7400 (Error)ProxyUnknownError. Message: XDebug proxy failed: {0}.
Run tyhp --explain TYHP7400 for the long-form explanation.
TYHP7401 (Warning)ProxySourceMapNotFound. Message: Sourcemap .{0} is not found
Run tyhp --explain TYHP7401 for the long-form explanation.
TYHP7402 (Warning)ProxySourceMapParseError. Message: Sourcemap .{0} is malformed: {1}
Run tyhp --explain TYHP7402 for the long-form explanation.
TYHP7403 (Error)ProxyConnectionFailed. Message: TCP connection failed: {0}.
Run tyhp --explain TYHP7403 for the long-form explanation.
TYHP7404 (Warning)ProxySessionPairingTimeout. Message: Debug session pairing wait for .{0} exceeds the timeout
Run tyhp --explain TYHP7404 for the long-form explanation.
TYHP7405 (Warning)ProxyTranslationError. Message: DBGp message translation failed: {0}.
Run tyhp --explain TYHP7405 for the long-form explanation.
TYHP7406 (Warning)ProxyInvalidDbgpMessage. Message: Malformed DBGp message is skipped: {0}.
Run tyhp --explain TYHP7406 for the long-form explanation.
TYHP7407 (Error)ProxyPortInUse. Message: Port .{0} is already in use
Run tyhp --explain TYHP7407 for the long-form explanation.
TYHP7500 (Error)TyhpdefGenerationError. Message: Tyhpdef generation failed: {0}.
Run tyhp --explain TYHP7500 for the long-form explanation.
TYHP7501 (Error)TyhpdefPhpNotFound. Message: PHP runtime is not found; .--ext-name requires PHP
Run tyhp --explain TYHP7501 for the long-form explanation.
TYHP7502 (Error)TyhpdefSourceParseError. Message: PHP source file .{0} failed to parse: {1}
Run tyhp --explain TYHP7502 for the long-form explanation.
TYHP7503 (Error)TyhpdefOutputWriteError. Message: Failed to write tyhpdef .{0}: {1}
Run tyhp --explain TYHP7503 for the long-form explanation.
TYHP7504 (Error)TyhpdefPhpDocParseError. Message: Failed to parse PHPDoc comment: {0}.
Run tyhp --explain TYHP7504 for the long-form explanation.
TYHP7505 (Error)TyhpdefLibraryEntrypointDetected. Message: Library projects cannot contain entrypoint files with executable top-level code: .{0}
Run tyhp --explain TYHP7505 for the long-form explanation.
TYHP7506 (Error)TyhpdefVerifyIncompatible. Message: .--verify found an incompatible tyhpdef for {0}
Run tyhp --explain TYHP7506 for the long-form explanation.
TYHP7507 (Error)TyhpdefSourceNotPhp. Message: Source path .{0} is not a .php file
Run tyhp --explain TYHP7507 for the long-form explanation.
TYHP7508 (Error)TyhpdefPhpRuntimeDownloadFailed. Message: Managed PHP runtime download failed: {0}.
Run tyhp --explain TYHP7508 for the long-form explanation.
TYHP7509 (Error)TyhpdefPhpRuntimeChecksumMismatch. Message: Managed PHP artifact checksum does not match.
Run tyhp --explain TYHP7509 for the long-form explanation.
TYHP7510 (Error)TyhpdefPhpUserBinaryWithTargets. Message: .--php cannot be combined with --php-targets
Run tyhp --explain TYHP7510 for the long-form explanation.
TYHP7511 (Error)TyhpdefPhpExtensionNotProvisioned. Message: Managed PHP cannot load extension .{0}
Run tyhp --explain TYHP7511 for the long-form explanation.
TYHP7512 (Warning)TyhpdefPhpRuntimeUpdateFailed. Message: Managed PHP patch update failed; using last-known-good runtime.
Run tyhp --explain TYHP7512 for the long-form explanation.
TYHP7513 (Warning)TyhpdefStubCacheMissing. Message: Layer 2 stub cache is missing at .{0}; skipping stub harvest
Run tyhp --explain TYHP7513 for the long-form explanation.
TYHP7514 (Error)TyhpdefStubCacheRequired. Message: .--require-stubs is set but the Layer 2 stub cache was not found at {0}
Run tyhp --explain TYHP7514 for the long-form explanation.
TYHP7515 (Warning)TyhpdefStubCorpusDisagreement. Message: Psalm and PHPStan disagree on .{0}; keeping the Layer 1 type
Run tyhp --explain TYHP7515 for the long-form explanation.
TYHP7516 (Error)TyhpdefVendorInstalledJsonMissing. Message: .vendor/composer/installed.json is not found at {0}
Run tyhp --explain TYHP7516 for the long-form explanation.
TYHP7517 (Error)TyhpdefVendorInstalledJsonInvalid. Message: .{0} is not valid Composer 2 installed.json: {1}
Run tyhp --explain TYHP7517 for the long-form explanation.
TYHP7518 (Warning)TyhpdefVendorCandidateFailed. Message: .--vendor candidate {0} failed: {1}
Run tyhp --explain TYHP7518 for the long-form explanation.
TYHP7519 (Warning)TyhpdefVendorComposerRequireFailed. Message: Composer require of .{0} failed: {1}
Run tyhp --explain TYHP7519 for the long-form explanation.
TYHP7520 (Error)TyhpdefVendorAllCandidatesFailed. Message: Every .--vendor candidate failed; found {0}
Run tyhp --explain TYHP7520 for the long-form explanation.
TYHP7521 (Error)TyhpdefStubUndeclaredTemplate. Message: Layer 2 stub overlay uses undeclared generic placeholder .{0}; not writing invalid tyhpdef
Run tyhp --explain TYHP7521 for the long-form explanation.
TYHP7522 (Warning)TyhpdefSourceFileSkipped. Message: Skipping unparseable PHP source .{0} during tyhpdef harvest: {1}
Run tyhp --explain TYHP7522 for the long-form explanation.
TYHP7523 (Warning)TyhpdefBundledPackagePreferred. Message: Bundled types in .{0} are used instead of {1}
Run tyhp --explain TYHP7523 for the long-form explanation.
TYHP7600 (Error)InitComposerJsonInvalid. Message: .{0} is not valid JSON: {1}
Run tyhp --explain TYHP7600 for the long-form explanation.
TYHP7601 (Warning)InitPhpConstraintUnsatisfied. Message: Existing .php constraint {0} cannot satisfy PHP {1}
Run tyhp --explain TYHP7601 for the long-form explanation.
TYHP7602 (Error)InitComposerJsonNotObject. Message: .{0} root is not a JSON object
Run tyhp --explain TYHP7602 for the long-form explanation.
TYHP7700 (Error)ComposerDisjointExtraRequire. Message: .extra.tyhp.require constraint {0} for {1} is disjoint from existing pin {2}
An extra.tyhp.require constraint is disjoint from the existing root pin for that package. Tyhp does not widen or clobber the pin. Align the extra with the pin, or change the root constraint so the two intersect, then re-run tyhp composer sync.
TYHP7701 (Error)ComposerStaleExtraRequire. Message: Stale extra .{0} is missing from root require-dev or is not installed
An installed package listed a stale extra.tyhp.require name that is not in this project's root require-dev (and not in require) or is not installed. The compiler cannot type-check against ambient types that are not loaded. Run tyhp composer sync or tyhp build --fix to write require-dev from the installed extra closure. If extras on packages that are not installed yet are unknown, run composer update so the tyhp/core plugin can resolve them. This check is local only and does not fetch Packagist.
TYHP7702 (Warning)ComposerMissingCompilerPin. Message: .tyhp/compiler is missing from root require-dev while {0} is in the graph
tyhp/compiler must be pinned on the application root require-dev whenever tyhp/core is in the Composer graph. The native CLI can keep running without that pin, so this is a warning unless --strict or build.strictMode is set. Run tyhp composer sync or tyhp build --fix to add the compiler pin.
TYHP7703 (Error)ComposerRootJsonWriteFailed. Message: root .composer.json at {0} cannot be parsed or written: {1}
The root composer.json could not be parsed or written while syncing extra.tyhp.require onto require-dev. Fix the JSON (or file permissions) and re-run tyhp composer sync.
TYHP7800 (Error)IntegrityCheckConfigInvalid. Message: Integrity check failed: project configuration is invalid.
Run tyhp --explain TYHP7800 for the long-form explanation.
TYHP7801 (Error)IntegrityCheckTyhpdefError. Message: Integrity check failed: one or more tyhpdef files could not be parsed.
Run tyhp --explain TYHP7801 for the long-form explanation.
TYHP7802 (Error)IntegrityCheckCacheCorrupted. Message: Integrity check failed: AST cache entries are corrupted or unreadable.
Run tyhp --explain TYHP7802 for the long-form explanation.
TYHP7803 (Error)IntegrityCheckEnvironmentError. Message: Integrity check failed: runtime environment problem detected.
Run tyhp --explain TYHP7803 for the long-form explanation.
TYHP7900 (Error)OverlayInvalidArguments. Message: Invalid .tyhp overlay command {0}; expected create <FQN> or stamp [<FQN>]
Run tyhp --explain TYHP7900 for the long-form explanation.
TYHP7901 (Error)OverlayTargetNotFound. Message: Overlay target .{0} was not found
Run tyhp --explain TYHP7901 for the long-form explanation.
TYHP7902 (Error)OverlayManifestUpdateFailed. Message: Failed to update overlay glob in .{0}
Run tyhp --explain TYHP7902 for the long-form explanation.
TYHP7903 (Error)OverlayWriteFailed. Message: Failed to write overlay tyhpdef for .{0}
Run tyhp --explain TYHP7903 for the long-form explanation.
TYHP7904 (Error)OverlayCreateOnExtern. Message: .overlay create cannot target extern type {0}
tyhp overlay create copies a real declaration into a hand-written overlay so that declaration can be replaced. An extern type is a name-only placeholder with no members; copying it would write a hollow class { } that looks like a complete empty type.
Write a full overlay class / interface / enum of the same name to upgrade the placeholder, or omit it. Extra extern names belong in an include file that regen does not overwrite, not in an overlay created from the placeholder.
TYHP7905 (Error)OverlayPhpRuntimeUnavailable. Message: Managed PHP runtime for .{0} is unavailable
tyhp overlay stamp writes @overlay-against once per managed PHP version. Each pass uses that version's managed runtime and stamps only declarations whose declare(php=…) or #[\Tyhp\Php] gate that runtime satisfies.
This error means the managed runtime for the named version is unavailable, so that pass is skipped. Declarations that belong only to that version are left unchanged. They are not stamped from a different PHP version. Restore the managed runtime cache (the same one generate_tyhpdef downloads) and run stamp again.
Tyhpdef errors are reported when loading or validating type-definition files.
TYHP8001 (Error)TyhpdefParseError. Message: Failed to parse tyhpdef file: {0}.
A .tyhpdef file contains syntax errors and could not be parsed.
Fix: Check the tyhpdef file for syntax errors. Tyhpdef syntax is similar to Tyhp but only supports declarations (no function bodies).
TYHP8002 (Error)TyhpdefDuplicateDeclaration. Message: Tyhpdef declares symbol .{0} which already exists
A tyhpdef file declares a symbol (class, function, constant) that is already declared by another tyhpdef or by the project's source code.
The primary span is the later include-layer declaration. A secondary span labeled "declared here" points at the first declaration of that name.
<?tyhpdef
class \App\User { } // first include — labeled "declared here"
<?tyhpdef
class \App\User { } // Error: Tyhpdef declares symbol `\App\User` which already exists
TYHP8003 (Error)TyhpdefFileNotFound. Message: Configured tyhpdef path .{0} does not exist
A tyhpdef file path specified in tyhp.json or via CLI arguments does not exist on disk.
TYHP8004 (Error)TyhpdefInvalidFormat. Message: Tyhpdef file .{0} has an unexpected structure
A tyhpdef file was parsed but its structure or format does not match what the compiler expects (e.g., missing required sections, invalid nesting).
TYHP8005 (Error)TyhpdefBindError. Message: Tyhpdef bind error: {0}.
A .tyhpdef file parsed, but binding it into the symbol table failed. The placeholder is the underlying bind exception text.
This is a semantic bind failure, not a parse error (TYHP8001).
Fix: Check the tyhpdef for unresolved names, illegal members, or other bind-time problems named in the message.
TYHP8010 (Error)TyhpdefExtensionConflict. Message: Extension member .{0} conflicts with a declared member on class {1}
A tyhpdef inline extension declares a member that collides with a member already declared on the same class.
TYHP8011 (Error)TyhpdefExtensionNotFound. Message: A .use extension reference in tyhpdef does not resolve to {0}
A use extension reference inside a tyhpdef file points to an extension that does not exist.
TYHP8012 (Error)TyhpdefInlineExtensionInvalidMember. Message: Invalid member with the .extension qualifier in tyhpdef
A member marked with the extension qualifier inside a tyhpdef declaration is not a valid extension member.
TYHP8013 (Error)TyhpdefExtensionOperatorRequiresBody. Message: .extension operator {0} requires a thin => expression; use bodyless operator {0}(…); (without extension) for native PHP operators
Run tyhp --explain TYHP8013 for the long-form explanation.
TYHP8014 (Error)TyhpdefPartialTargetNotFound. Message: .partial type {0} does not exist in this compilation's include set
Run tyhp --explain TYHP8014 for the long-form explanation.
TYHP8015 (Error)TyhpdefPropertyHookBodyNotAllowed. Message: Tyhpdef property hooks must be bodyless.
A tyhpdef hooked property is a bodyless signature list: { get; set; }, { get; }, or { &get; set; }. Brace and arrow bodies (get { … }, get => …) belong in .tyhp source, not .tyhpdef.
Write public string $name { get; set; } to describe a hooked PHP property. A hooked declaration names one $name.
TYHP8016 (Error)TyhpdefPhpVersionGateOnPropertyHook. Message: .#[\Tyhp\Php] is not allowed on a property hook; place it on the property or wrap with declare(php=...)
#[\Tyhp\Php] on an individual get or set is not a version gate. Place the attribute on the property, or wrap the declaration with declare(php=…).
<?tyhpdef
class Holder {
#[\Tyhp\Php(">=8.4")]
public string $name { get; set; }
}
TYHP8017 (Error)TyhpdefOmitOutsideOverlay. Message: .omit is only allowed in overlay tyhpdef files
Run tyhp --explain TYHP8017 for the long-form explanation.
TYHP8018 (Error)TyhpdefIllegalKeywordCombination. Message: .partial, omit, deprecated, obsolete, and extern cannot be combined on the same declaration, and fallback cannot be combined with partial, omit, or extern
Run tyhp --explain TYHP8018 for the long-form explanation.
TYHP8019 (Warning)TyhpdefOverlayPartialTargetNotFound. Message: Overlay .partial has no matching type {0} in the environment; skipped
Run tyhp --explain TYHP8019 for the long-form explanation.
TYHP8020 (Warning)TyhpdefOmitMissingSymbol. Message: Overlay .omit has no matching symbol {0} in the environment
Run tyhp --explain TYHP8020 for the long-form explanation.
TYHP8021 (Error, Warning)TyhpdefOverlayStampMismatch. Message: .@overlay-against for {0} does not match the Layer 1 baseline signature
Run tyhp --explain TYHP8021 for the long-form explanation.
TYHP8022 (Warning)TyhpdefOverlayIncompatibleReplace. Message: Overlay replace of .{0} is not a compile-time-compatible rewrite of the Layer 1 baseline
Run tyhp --explain TYHP8022 for the long-form explanation.
TYHP8025 (Error)TyhpdefDuplicateFqnAcrossPackages. Message: Fully-qualified name .{0} is defined in packages {1} and {2}
Run tyhp --explain TYHP8025 for the long-form explanation.
TYHP8026 (Warning)TyhpdefPhpExtensionPackageNotFound. Message: PHP extension package not found; install .tyhpdef/php via Composer for full PHP built-in type checking
Run tyhp --explain TYHP8026 for the long-form explanation.
TYHP8027 (Warning)TyhpdefRuntimePackageNotFound. Message: Runtime package not found for .tyhp/{0}; install the package via Composer for full type checking
Run tyhp --explain TYHP8027 for the long-form explanation.
TYHP8028 (Error)TyhpdefExternIllegalDeclaration. Message: .extern name {0} is not name-only
An extern declaration must be name-only: extern \Foo\Bar;, extern class \Foo\Bar; (or interface / enum), extern function \bcadd;, or extern const \FOO; with a semicolon and no members or signature. A body, members, generics, extends / implements on the placeholder, an as alias, abstract / final / readonly, a backing type on enum, extern trait, or a parameter list / return type / value on extern function / const is an illegal declaration.
Grammar rejects most of these at parse time. This code is for visitor or binder paths that still see an invalid form.
TYHP8029 (Error)TyhpdefExternKindMismatch. Message: Name .{0} is declared as {1} and {2}
The kind of an extern placeholder does not match another declaration of the same name in the same PHP name space. extern class Foo against a real interface Foo, or extern class Foo against extern interface Foo, is a kind mismatch. A kind-unspecified extern Foo; is compatible with a later real class, interface, or enum. Functions, constants, and types occupy separate PHP name spaces, so extern function Foo may coexist with class Foo.
A later real declaration of the same fully-qualified name and kind silently replaces a compatible placeholder. Two externs of the same kind merge. This diagnostic is only the kind conflict. The {1} and {2} placeholders are the two kinds (for example extern class and interface).
TYHP8030 (Error)TyhpdefPartialOnExtern. Message: .partial cannot target extern {0}
Overlay or include partial targeted an extern name. Partial would add members or attributes to a name-only placeholder, which is not allowed.
Full overlay replace with a real class / interface / enum / function / const of the same name upgrades the placeholder (a kind-unspecified extern \Name; accepts class, interface, or enum). omit of an extern is allowed and removes the name.
TYHP8031 (Warning)TyhpdefPartialFunctionTargetNotFound. Message: Overlay .partial function has no matching {0} in the environment; skipped
Overlay partial function names a function or method that is not in the environment left by include files and earlier overlays. The missing target is skipped; no attributes are merged.
Match the Tyhp name of an existing callable. partial function does not add a new symbol. Use a full overlay function or method declaration to introduce a name.
TYHP8032 (Error)TyhpdefPartialFunctionOutsideOverlay. Message: .partial function is only allowed in overlay tyhpdef files
partial function is overlay-only. It merges attributes onto an existing callable without restating the signature.
Using it outside an overlay file is an error. Put name-only partial function declarations in an overlay tyhpdef (extra.tyhp.package / tyhp.json "overlay"). Include / baseline files still declare full signatures.
TYHP8033 (Error)TyhpdefPartialFunctionMemberOutsidePartialType. Message: .partial function as a member is only allowed inside overlay partial types
A partial function member is only valid inside an overlay partial type. That is the merge path that keeps other members and unions attributes onto the matching method.
Write partial class DateTime { #[\Tyhp\Optimize\Pure] partial function format; }. A full overlay class replace restates methods with their signatures instead.
TYHP8034 (Error)TyhpdefPartialTypeHeaderOutsideOverlay. Message: .partial {0} header form (semicolon) is only allowed in overlay tyhpdef files
The semicolon header form partial class Foo<T>; (also interface / trait / enum) is overlay-only. It replaces written header clauses on an existing type and keeps unlisted members.
Using it outside an overlay file is an error. Put header-only partial declarations in an overlay tyhpdef (extra.tyhp.package / tyhp.json "overlay"). Include / baseline files still use brace partial to add members, or a full type declaration.
TYHP8035 (Warning)TyhpdefPartialTypeHeaderNoEffect. Message: Overlay .partial {0} {1}; does not change the type
A bare overlay partial class Foo; has no effect: it does not change generics, inheritance, attributes, or names. It is only useful as a keep so the same overlay file can also declare partial class Foo as Bar;.
Add generics, extends / implements, attributes, or as, or pair the bare keep with an alias in the same overlay file. Otherwise omit the declaration.
TYHP8036 (Error)TyhpdefFallbackOrderUnknown. Message: fallback function .{0} is declared by more than one package, and Composer autoload file order cannot choose a winner
Run tyhp --explain TYHP8036 for the long-form explanation.
TYHP8037 (Warning)TyhpdefFallbackSignatureMismatch. Message: fallback function .{0} from {1} does not match the signature from {2}; the later declaration is ignored
Run tyhp --explain TYHP8037 for the long-form explanation.
TYHP8038 (Error)TyhpdefFallbackRedeclare. Message: function .{0} in {1} is loaded after fallback function {0} in {2} and would be a fatal redeclaration in PHP
Run tyhp --explain TYHP8038 for the long-form explanation.
TYHP8039 (Error)TyhpdefExtDeclareNotAlone. Message: .declare(ext=…) must be the only directive in that declare
Run tyhp --explain TYHP8039 for the long-form explanation.
TYHP8040 (Error)TyhpdefExtDeclareInvalid. Message: .declare(ext=...) must name an extension, or ! plus that name; got {0}
Run tyhp --explain TYHP8040 for the long-form explanation.
TYHP8041 (Error)TyhpdefFallbackConstOrderUnknown. Message: fallback const .{0} is declared by more than one package, and Composer autoload file order cannot choose a winner
Run tyhp --explain TYHP8041 for the long-form explanation.
TYHP8042 (Warning)TyhpdefFallbackConstMismatch. Message: fallback const .{0} from {1} does not match the constant from {2}; the later declaration is ignored
Run tyhp --explain TYHP8042 for the long-form explanation.
TYHP8043 (Error)TyhpdefFallbackConstRedeclare. Message: const .{0} in {1} is loaded after fallback const {0} in {2} and would be a fatal redeclaration in PHP
Run tyhp --explain TYHP8043 for the long-form explanation.