Silencing Errors: Introduction

Errors reported by the Hack typechecker can be silenced with HH_FIXME and HH_IGNORE_ERROR comments. Errors arising from type mismatches on expressions may also be silenced using the HH\FIXME\UNSAFE_CAST function.

Silencing Errors with HH\FIXME\UNSAFE_CAST

takes_int(HH\FIXME\UNSAFE_CAST<string,int>("foo",  "Your explanation here"));

To silence an error arising from a type mismatch on a particular expression, add a call to HH\FIXME\UNSAFE_CAST with the expression as the first argument, an optional (string literal) comment, and explicit type hints indicating the actual type of the expression and the expected type.

The UNSAFE_CAST function has no runtime effect. However, in contrast to HH_FIXME comments, the UNSAFE_CAST function does change the type of the expression.

Silencing Errors per Expression

Whilst a single HH_FIXME comment will silence all related errors on the proceeding line, the UNSAFE_CAST function must be applied to each sub-expression that has a type mismatch.

function takes_int(int $i): int {
  return $i + 1;
}

function takes_float_with_fixme(float $i): float {
  /* HH_FIXME[4110] calls takes_int with wrong
     param type AND returns wrong type */
  return takes_int($i);
}
function takes_float_with_unsafe_cast(float $i): float {
  return HH\FIXME\UNSAFE_CAST<int, float>(
    takes_int(HH\FIXME\UNSAFE_CAST<float, int>($i, 'wrong param type')),
    'returns wrong type',
  );
}

Silencing Errors with Comments

/* HH_FIXME[4110] Your explanation here. */
takes_int("foo");

To silence an error, place a comment on the immediately previous line. The comment must use the /* syntax.

This syntax only affects error reporting. It does not change types, so the typechecker will keep checking the rest of the file as before.

This syntax also has no runtime effect. The runtime will do its best with badly typed code, but it may produce an error immediately, produce an error later in the program, or coerce values to an unwanted type.

The behavior of badly typed code may change between HHVM releases. This will usually be noted in the changelog.

HH_FIXME versus HH_IGNORE_ERROR

Both HH_FIXME and HH_IGNORE_ERROR have the same effect: they suppress an error.

/* HH_FIXME[4110] An example fixme. */
takes_int("foo");

/* HH_IGNORE_ERROR[4110] This is equivalent to the HH_FIXME above. */
takes_int("foo");

You should generally use HH_FIXME. HH_IGNORE_ERROR is intended to signal to the reader that the type checker is wrong and you are deliberately suppressing the error. This should be very rare.

Error Codes

Every Hack error has an associated error code. These are stable across Hack releases, and new errors always have new error codes.

Hack will ignore error suppression comments that have no effect, to help migration to newer Hack versions.

Error codes 1000 - 1999 are used for parsing errors. Whilst it is possible to silence these, the runtime usually cannot run this code at all.

Error codes 2000 - 3999 are used for naming errors. This includes references to nonexistent names, as well as well-formedness checks that don't require type information.

Error codes 4000 - 4999 are used for typing errors.

Configuring Error Suppression

Hack error suppression can be configured in the .hhconfig file at the root of a project. In hhvm version 4.62 and above, error suppression works on a whitelist system. Older hhvm versions used a blacklisting system instead.

How to whitelist suppression comments in hhvm 4.62 and above

By default Hack will not accept a suppression comment, if that specific error code is not mentioned in the .hhconfig file. Attempting to suppress an unmentioned error will result in an extra error like this:

Typing[4110] You cannot use HH_FIXME or HH_IGNORE_ERROR comments to suppress error 4110

If the file in which this error resides is in partial mode, add 4110 to the allowed_fixme_codes_partial key in your .hhconfig. If the file in which this error resides is in strict mode, add 4110 to the allowed_fixme_codes_strict key in your .hhconfig.

As described further in Best Practices, suppressing errors on declarations is generally a bad idea. However, some errors can only be suppressed at a declaration. When suppressing an error at a declaration, you'll get an error like this.

Typing[4047] You cannot use HH_FIXME or HH_IGNORE_ERROR comments to suppress error 4047 in declarations

In such cases, you'll have to add 4047 to the allowed_decl_fixme_codes key, as well as to the allowed_fixme_codes_xxx key.

An important note when using an external package. If a package uses a suppression comment and mentions this in its .hhconfig, this will not automatically update the .hhconfig settings for your project. In order to use this package, you'll need to add these codes to your own .hhconfig.

Historic note for hhvm 4.61 and below

If you are writing code on hhvm 4.62 or above, you may skip this section.

Once you have removed all the occurrences of a specific error code, you can ensure that no new errors are added.

You can use the ignored_fixme_codes option in .hhconfig to forbid suppression of a specific error code.

ignored_fixme_codes = 1002, 4110

This forbids /* HH_FIXME[4110] ... */.

.hhconfig also supports disallowed_decl_fixmes, which forbids error suppression of specific error codes on declarations (types, class properties etc).

disallowed_decl_fixmes = 1002, 4110

This forbids /* HH_FIXME[4110] ... */ outside of function and method bodies.

Partial mode files have fewer checks. You can opt-in to specific strict mode checks in partial files by using the error code in error_codes_treated_strictly in .hhconfig.

error_codes_treated_strictly = 1002, 2045, 2055, 2060, 4005

Best Practices

Great Hack code has no error suppressing comments, and only uses strict mode.

Suppressing errors in one place can lead to runtime errors in other places.

function takes_int(int $_): void {}

function return_ints_lie(): vec<int> {
  /* HH_FIXME[4110] The type error is here. */
  return vec["foo"];
}

<<__EntryPoint>>
function oh_no(): void {
  $items = return_ints_lie();
  takes_int($items[0]); // But the exception is here!
}

Good Hack code has no error suppression comments on its declarations. Suppressing errors in declarations can hide a large number of issues elsewhere.

function takes_int(int $_): void {}
function takes_float(float $_): void {}

/* HH_FIXME[4030] Missing a return type. */
function returns_something() {
  return "";
}

function oh_no(): void {
  // This is wrong.
  takes_int(returns_something());
  // This is wrong too!
  takes_float(returns_something());
}

When you use error suppression, make sure you specify a reason. Try to keep your comments to small expressions, because the comment applies to the entire next line.

/* HH_FIXME[4110] Bad: this can apply to both function calls! */
$result = foo(bar("stuff"));

/* HH_FIXME[4110] Better: we will spot errors when calling bar. */
$x = foo("stuff");
$result = bar($x);
Was This Page Useful?
Thank You!
Thank You! If you'd like to share more feedback, please file an issue.