constructor(severity, category, code, ...varArgs) {
    /**
     * @override
     * @exportInterface
     */
    this.severity = severity;
    /**
     * @override
     * @exportInterface
     */
    this.category = category;
    /**
     * @override
     * @exportInterface
     */
    this.code = code;
    /**
     * @override
     * @exportInterface
     */
    this.data = varArgs;
    /**
     * @override
     * @exportInterface
     */
    this.handled = false;

    // A basic message for compiled mode.
    let formattedMessage = 'Shaka Error ' + this.code;
    if (goog.DEBUG) {
      // This improves the formatting of Errors in failure messages in the
      // tests in debug mode.
      let categoryName = 'UNKNOWN';
      let codeName = 'UNKNOWN';

      for (const k in shaka.util.Error.Category) {
        if (shaka.util.Error.Category[k] == this.category) {
          categoryName = k;
        }
      }
      for (const k in shaka.util.Error.Code) {
        if (shaka.util.Error.Code[k] == this.code) {
          codeName = k;
        }
      }

      formattedMessage = 'Shaka Error ' + categoryName + '.' + codeName +
                         ' (' + this.data.toString() + ')';
    }

    /**
     * In compiled mode, contains a basic message string with the error code.
     * In uncompiled and debug modes, contains a human-readable version of the
     * category and code as enums.
     *
     * @const {string}
     * @exportDoc
     */
    this.message = formattedMessage;

    if (shaka.util.Error.createStack) {
      try {
        throw new Error(this.message || 'Shaka Error');
      } catch (e) {
        /**
         * A stack-trace showing where the error occurred.
         *
         * @const {string}
         * @exportDoc
         */
        this.stack = e.stack;
      }
    }
  }
@param {shaka.util.Error.Severity} severity
@param {shaka.util.Error.Category} category
@param {shaka.util.Error.Code} code
@param {...*} varArgs