Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Scala 3  Module 1 – Start here: Scala 3.9 LTS on the JVM

Read Scala compiler errors and warnings

Read a Scala 3 diagnostic from its code, position and Found and Required types, fix common errors at the cause, and use -explain, -Wunused:all and -Werror.

  • Beginner
  • 15 minutes
  • Examples run with scala 3.9.0, Java 25.0.4.1 and Python 3.14.8
  • By MySmartCoPilot
Free: 15 minutes

What you will learn

  • Read a Scala 3 diagnostic from its code, file position, caret and Found and Required types
  • Fix the cause of errors E007, E171 and E172 rather than the symptom
  • Explain why warning E029 lets the build pass and how -Werror makes it fail
  • Use -explain, -deprecation, -feature and -Wunused:all to see what the compiler holds back
  • Find a diagnostic's code in the Scala 3 Reference and fix the first error first

Before you start

What you’ll learn · Before you start

What you will learn

  • Read a Scala 3 diagnostic from its code, file position, caret and Found and Required types
  • Fix the cause of errors E007, E171 and E172 rather than the symptom
  • Explain why warning E029 lets the build pass and how -Werror makes it fail
  • Use -explain, -deprecation, -feature and -Wunused:all to see what the compiler holds back
  • Find a diagnostic's code in the Scala 3 Reference and fix the first error first

Before you start

On this page

A Scala 3 error message names a code, a place and two types: [E007] Type Mismatch Error on line 2, column 25, Found: ("4250" : String), Required: Long. Read in that order, most messages tell you what to change before you even look at the code.

This lesson takes one message apart, fixes three common errors at their cause, shows a warning that compiles and then crashes the program, turns on the flags that reveal what the compiler holds back, and ends with a broken receipt for you to repair.

A diagnostic names a code, a place and two types

Every message the compiler prints about your code is a diagnostic: A message from the compiler about the source: an error, which stops the build, or a warning, which does not. Scala 3 diagnostics carry a code such as E007.: an error, which stops the build, or a warning, which does not. Here is a three-line program with one mistake, a number written as text:

errors/Mismatch.scala Scala · errors/Mismatch.scala
@main def checkout(): Unit =
  val totalCents: Long = "4250"
  println(totalCents)

The session compiles it twice, the second time with -explain. Like every session of this track it uses --server=false, so the messages appear exactly as the compiler writes them; the Scala CLI documentation notes that the compile server at times gets in the way of the full compiler output. The session also shortens the file’s full path to its name:

One type error, plain and with -explain Python · mismatch_session.py
from session import run

# One type error, first as the compiler reports it, then with the longer explanation that -explain adds.
run("""
cd errors
!scala compile Mismatch.scala --server=false
!scala compile Mismatch.scala --server=false -explain
""")

Output

$ cd errors
$ scala compile Mismatch.scala --server=false
-- [E007] Type Mismatch Error: Mismatch.scala:2:25
2 |  val totalCents: Long = "4250"
  |                         ^^^^^^
  |                         Found:    ("4250" : String)
  |                         Required: Long
  |
  | longer explanation available when compiling with `-explain`
1 error found
Compilation failed
[exit status 1]
$ scala compile Mismatch.scala --server=false -explain
-- [E007] Type Mismatch Error: Mismatch.scala:2:25
2 |  val totalCents: Long = "4250"
  |                         ^^^^^^
  |                         Found:    ("4250" : String)
  |                         Required: Long
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |
  | Tree:
  |
  | "4250"
  |
  | I tried to show that
  |   ("4250" : String)
  | conforms to
  |   Long
  | but none of the attempts shown below succeeded:
  |
  |   ==> ("4250" : String)  <:  Long
  |     ==> String  <:  Long  = false
  |
  | The tests were made under the empty constraint
   -----------------------------------------------------------------------------
1 error found
Compilation failed
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 mismatch_session.py

Read the first message from the top: the code and the kind of problem, the file with its line and column, the line itself with a caret under the part that is wrong, then the two types. Found is the type of what you wrote, here the literal "4250", shown as ("4250" : String): the type of exactly that string, which is a String. Required is the type the place needs, Long, because totalCents was declared as one. The fix follows from the two lines: write the number, 4250, or declare a String if you meant text. The last lines count the problems and say the build failed.

-explain adds the compiler’s reasoning: it tried to show that ("4250" : String) conforms to Long, that is, that a String can be used where a Long is needed, and every attempt failed. For a plain mismatch the short message is enough; for an error you do not understand, the explanation shows which comparison failed. Step through the parts of the message in the order to read them:

Interactive · stage by stage Reading one diagnostic, part by part Step through the E007 message of the session from its first line to its last. Each step reads one part.
Reading one diagnostic, part by part, step 6 of 6. Showing [E007] Type Mismatch, Mismatch.scala:2:25, The line and its caret, Found: ("4250" : String), Required: Long, 1 error found. In focus: 1 error found.[E007] Type Mismatchthe code and the kindMismatch.scala:2:25file, line and columnThe line and its caretwhat is wrong in itFound: ("4250" : String)the type you wroteRequired: Longthe type the place needs1 error foundand Compilation failed

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. The code. [E007] names the kind of problem with a number you can look up in the Scala 3 Reference: E007 is Type Mismatch. Error means the build stops; a warning would say Warning.
  2. The place. Mismatch.scala:2:25 is the file, the line and the column where the problem starts. Editors turn this part into a link to that spot.
  3. The caret. The compiler prints line 2 and puts carets under "4250", the part it could not accept. The rest of the line was fine.
  4. Found. Found is the type of what you wrote. ("4250" : String) is the type of exactly that string, which is a String.
  5. Required. Required is the type the place needs. totalCents was declared as a Long, so it needs a Long. The fix is the difference between the two lines.
  6. The summary. The count of errors and Compilation failed close the output. With -explain, a longer explanation comes before them.

Key idea

Read a diagnostic in order: the code, the place, the caret, then Found against Required; the difference between the two types is usually the fix.

Checkpoint

Check: Reading a diagnostic

  1. Question 1 of 2 A message says Found: ("4250" : String) and Required: Long. Which of the two lines describes what you wrote?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Found

    Found is what you wrote and Required is what the place needs. Here a String was written where a Long is needed, so write the number 4250 or change the declared type.

  2. Question 2 of 2 What does compiling with -explain add to the E007 message?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The compiler's reasoning, the check that ("4250" : String) conforms to Long and why it failed

    -explain prints the reasoning behind a message. For E007 it shows that the compiler tried to show that the String conforms to Long and that the attempt failed.

Fix the cause: a missing argument and a missing given

Two more errors appear in nearly every first week. The session below compiles a call with one argument too few, then a sort of a list whose element type has no ordering, then tries the import that the second message suggests, and finally runs the fixed program:

errors/Ordering.scala Scala · errors/Ordering.scala
case class Price(cents: Long)

@main def cheapestFirst(): Unit =
  val prices = List(Price(450), Price(120), Price(1599))
  println(prices.sorted)
E171, E172, a suggested import, and the fix Python · causes_session.py
from session import run

# A missing argument, a missing given, the import that the second message suggests, and the two fixes that work.
run("""
cd errors
!scala compile Arity.scala --server=false
!scala compile Ordering.scala --server=false
cd ../imported
!scala compile Ordering.scala --server=false
cd ../fixes
scala run CheapestFirst.scala --server=false
""")

Output

$ cd errors
$ scala compile Arity.scala --server=false
-- [E171] Type Error: Arity.scala:4:19
4 |  println(lineTotal(450))
  |          ^^^^^^^^^^^^^^
  |missing argument for parameter quantity of method lineTotal: (unitCents: Long, quantity: Int): Long
1 error found
Compilation failed
[exit status 1]
$ scala compile Ordering.scala --server=false
-- [E172] Type Error: Ordering.scala:5:23
5 |  println(prices.sorted)
  |                       ^
  |No given instance of type Ordering[B] was found for parameter ord of method sorted in trait StrictOptimizedSeqOps.
  |I found:
  |
  |    scala.math.Ordering.ordered[B](
  |      /* missing */summon[scala.math.Ordering.AsComparable[B]])
  |
  |But no implicit values were found that match type scala.math.Ordering.AsComparable[B]
  |
  |where:    B is a type variable with constraint >: Price
  |.
  |
  |The following import might make progress towards fixing the problem:
  |
  |  import scala.math.Ordered.orderingToOrdered
  |
1 error found
Compilation failed
[exit status 1]
$ cd ../imported
$ scala compile Ordering.scala --server=false
-- [E172] Type Error: Ordering.scala:7:23
7 |  println(prices.sorted)
  |                       ^
  |No given instance of type Ordering[B] was found for parameter ord of method sorted in trait StrictOptimizedSeqOps.
  |I found:
  |
  |    scala.math.Ordering.ordered[B]((x: Price) =>
  |      scala.math.Ordered.orderingToOrdered[T](x)(
  |        scala.math.Ordering.comparatorToOrdering[T](
  |          /* missing */summon[java.util.Comparator[T]])
  |      )
  |    )
  |
  |But method orderingToOrdered in object Ordered does not match type scala.math.Ordering.AsComparable[B]
  |
  |where:    B is a type variable with constraint >: Price
  |.
1 error found
Compilation failed
[exit status 1]
$ cd ../fixes
$ scala run CheapestFirst.scala --server=false
List(Price(120), Price(450), Price(1599))
List(Price(120), Price(450), Price(1599))

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 causes_session.py

[E171], missing argument for parameter quantity, comes with the full signature of the method, so you can see which parameter is missing and its type. [E172] is longer, but only its first line says what is wrong: No given instance of type Ordering[B] was found for parameter ord of method sorted, where B is any type above Price. In plain words: sorted needs to know how to order prices, and nobody has said. The rest of the message is the compiler’s search: what it tried, what was missing, and an import that “might make progress”. Here is what each of the four errors of this lesson means, and the fix that removes its cause:

Code and name The usual cause A fix that removes the cause
E007 Type Mismatch Found is not Required: a value of the wrong type, often a number as text pass a value of the required type, or change the declared type
E171 Missing Argument a call with fewer arguments than parameters pass the argument, or give the parameter a default value
E172 Missing Implicit Argument a method needs a given instance: A value that the compiler passes by itself to a parameter declared with using, chosen by its type. sorted, for example, needs a given Ordering for the element type. that nobody defined define one, such as an Ordering, or call a method that takes the rule directly
E029 Pattern Match Exhaustivity, a warning a match without a case for some value add the missing case
fixes/CheapestFirst.scala Scala · fixes/CheapestFirst.scala
// Two fixes for the missing Ordering: sort by a key, or give Price an ordering in its companion object.
case class Price(cents: Long)

object Price:
  given Ordering[Price] = Ordering.by(_.cents)

@main def cheapestFirst(): Unit =
  val prices = List(Price(450), Price(120), Price(1599))
  println(prices.sortBy(_.cents))
  println(prices.sorted)

The fixed program shows both cures for E172: sortBy(_.cents) says how to order right where it sorts, and a given Ordering[Price] in the companion object of Price gives prices an ordering that every sorted finds, wherever it is called. Both print the prices from cheapest to dearest.

Adding the import that the message suggests

The session added the import the message suggested, scala.math.Ordered.orderingToOrdered. The error stayed: the compiler’s search only grew longer, and no import was suggested any more. Such imports only convert between kinds of order that a type already has, such as an Ordering or a class that extends Ordered. Price has none, so give it one, as the fixed program does.

Checkpoint

Check: Fixing E171 and E172 at the cause

  1. Question 1 of 2 This call fails with missing argument for parameter quantity. Which call compiles and asks for a basket of two at 450 cents each?

    Read the code, then choose one answer.

    def lineTotal(unitCents: Long, quantity: Int): Long = unitCents * quantity
    
    println(lineTotal(450))
    Show the answer: Question 1 of 2

    Answer: lineTotal(450, 2)

    E171 names the missing parameter and the method's full signature. Pass the argument it names, in its place, or give the parameter a default value if most calls use the same quantity.

  2. Question 2 of 2 prices.sorted fails with E172 for case class Price(cents: Long). What is the cause?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: There is no Ordering for Price, and sorted needs one to compare two prices

    sorted takes a using parameter of type Ordering. Give Price one, for example a given in its companion object built with Ordering.by(_.cents), or sort with sortBy(_.cents), which takes the key directly.

A warning compiles, and can still crash the program

Warnings do not stop the build. Usually that is right, but some warnings predict a crash. This program charges a fee for three ways to pay, and its match forgets one of them:

errors/Fees.scala Scala · errors/Fees.scala
enum Payment:
  case Card, Wallet, Cash

def feeCents(p: Payment): Long = p match
  case Payment.Card   => 30
  case Payment.Wallet => 10

@main def fees(): Unit =
  for p <- Payment.values do println(s"$p: ${feeCents(p)} cents")
A non-exhaustive match: compiled, run, refused and fixed Python · fees_session.py
from session import run

# A warning that compiles: the build passes, the program crashes on the case the warning named, and -Werror stops it.
run("""
cd errors
scala compile Fees.scala --server=false
!scala run Fees.scala --server=false
!scala compile Fees.scala --server=false -Werror
cd ../fixes
scala run Fees.scala --server=false
""")

Output

$ cd errors
$ scala compile Fees.scala --server=false
-- [E029] Pattern Match Exhaustivity Warning: Fees.scala:4:33
4 |def feeCents(p: Payment): Long = p match
  |                                 ^
  |                                 match may not be exhaustive.
  |
  |                                 It would fail on pattern case: Cash
  |
  | longer explanation available when compiling with `-explain`
1 warning found
$ scala run Fees.scala --server=false
-- [E029] Pattern Match Exhaustivity Warning: Fees.scala:4:33
4 |def feeCents(p: Payment): Long = p match
  |                                 ^
  |                                 match may not be exhaustive.
  |
  |                                 It would fail on pattern case: Cash
  |
  | longer explanation available when compiling with `-explain`
1 warning found
Card: 30 cents
Wallet: 10 cents
Exception in thread "main" scala.MatchError: Cash (of class Payment$$anon$1)
	at Fees$package$.feeCents(Fees.scala:6)
	at Fees$package$.fees$$anonfun$1(Fees.scala:9)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1324)
	at Fees$package$.fees(Fees.scala:9)
	at fees.main(Fees.scala:8)
[exit status 1]
$ scala compile Fees.scala --server=false -Werror
-- [E029] Pattern Match Exhaustivity Warning: Fees.scala:4:33
4 |def feeCents(p: Payment): Long = p match
  |                                 ^
  |                                 match may not be exhaustive.
  |
  |                                 It would fail on pattern case: Cash
  |
  | longer explanation available when compiling with `-explain`
No warnings can be incurred under -Werror
1 warning found
1 error found
Compilation failed
[exit status 1]
$ cd ../fixes
$ scala run Fees.scala --server=false
Card: 30 cents
Wallet: 10 cents
Cash: 0 cents

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 fees_session.py

The compile printed [E029] Pattern Match Exhaustivity Warning and named the value that no case covers, Cash, but it ended with 1 warning found and status 0, so a build would pass. The run then printed the first two fees and crashed on the third with scala.MatchError: Cash, the exact value the warning had named. -Werror turns every warning into an error, No warnings can be incurred under -Werror, so the same mistake fails the build instead of the program. The fixed version has a case for Cash and prints all three fees.

The match is an exhaustive match: A match with a case for every possible value of its type. When the compiler finds a value that no case covers, it warns with E029, and that value throws MatchError at run time. once it covers every value of Payment. For an enum the compiler knows all the values, which is why it can name the missing one; when someone later adds a fourth way to pay, the same warning names that one too. Step through the run that crashed, then the fix:

Interactive · stage by stage From a warning to a crash, and how -Werror stops it Step through the compile and the run of errors/Fees.scala, then the fix. The branch shows the same compile with -Werror.
From a warning to a crash, and how -Werror stops it, step 8 of 8. Showing scala compile, The build passes, feeCents(Card), feeCents(Wallet), feeCents(Cash), scala.MatchError, A case for Cash. In focus: scala compile, A case for Cash.with -Werrorscala compileE029: it would fail on CashThe build passes1 warning found, status 0feeCents(Card)30 centsfeeCents(Wallet)10 centsfeeCents(Cash)no case matchesscala.MatchErrorCash, the named valueA case for Cashall three fees printbuild fails

The drawing shows the whole scene; its 8 steps are listed below.

Every step as text
  1. The warning. The compiler finds that no case covers Payment.Cash and prints E029: match may not be exhaustive, it would fail on pattern case Cash.
  2. The build passes. A warning does not stop the build. The compile ends with 1 warning found and status 0, so a build script or CI would carry on.
  3. Card. The program loops over Payment.values. Card matches its case and prints 30 cents.
  4. Wallet. Wallet matches the second case and prints 10 cents.
  5. Cash. Cash matches no case. A match without a case for its value cannot return anything, so it throws.
  6. MatchError. The program stops with scala.MatchError for Cash, the very value the warning named, and exit status 1.
  7. The fix. fixes/Fees.scala gives Cash a case of its own, case Payment.Cash => 0. It compiles without a warning and prints all three fees, the last one Cash: 0 cents.
  8. With -Werror. Compiled with -Werror, the same warning becomes an error, No warnings can be incurred under -Werror, and nothing is built. The only way on is the fix, before any program can crash.

Silencing E029 with case _

Adding case _ => 0 makes the warning go away, and with it every future warning about this match: a fourth way to pay added next year would cost nothing, without a word from the compiler. Name each value in its own case, as fixes/Fees.scala does, and keep the warning working for you.

Checkpoint

Check: Warnings that predict a crash

  1. Question 1 of 2 scala compile Fees.scala printed the E029 warning. With which exit status did the compile end?

    Type a number.

    A hint

    A warning is not an error. Look for an [exit status] line after the compile in the session.

    Show the answer: Question 1 of 2

    Answer: 0 exit status

    A warning does not fail the build, so the compile ended with status 0, and only the run crashed. With -Werror the same compile ends with status 1.

  2. Question 2 of 2 What does -Werror change for Fees.scala?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The E029 warning becomes an error, so the build fails and the program is never built

    With -Werror the compile prints the warning, says No warnings can be incurred under -Werror, and fails, so the bug cannot reach a running program.

Flags show what the compiler holds back

Some warnings appear only when you ask for them, and some arrive as a one-line summary until you do. The session compiles three small programs with and without the flag that shows each kind:

Unused values, deprecations and features Python · flags_session.py
from session import run

# What the compiler holds back until a flag asks for it: unused values, deprecations and language features.
run("""
cd errors
scala compile Unused.scala --server=false
scala compile Unused.scala --server=false -Wunused:all
!scala compile Unused.scala --server=false -Wunused:all -Werror
scala compile Deprecated.scala --server=false
scala compile Deprecated.scala --server=false -deprecation
scala compile Conversion.scala --server=false
scala compile Conversion.scala --server=false -feature
""")

Output

$ cd errors
$ scala compile Unused.scala --server=false
$ scala compile Unused.scala --server=false -Wunused:all
-- [E198] Unused Symbol Warning: Unused.scala:2:6
2 |  val taxPercent = 18
  |      ^^^^^^^^^^
  |      unused local definition
1 warning found
$ scala compile Unused.scala --server=false -Wunused:all -Werror
-- [E198] Unused Symbol Warning: Unused.scala:2:6
2 |  val taxPercent = 18
  |      ^^^^^^^^^^
  |      unused local definition
No warnings can be incurred under -Werror
1 warning found
1 error found
Compilation failed
[exit status 1]
$ scala compile Deprecated.scala --server=false
there was 1 deprecation warning; re-run with -deprecation for details
1 warning found
$ scala compile Deprecated.scala --server=false -deprecation
-- Deprecation Warning: Deprecated.scala:7:10
7 |  println(total(List(450, 120)))
  |          ^^^^^
  |method total is deprecated since 2.0: use totalCents, which counts the discount
1 warning found
$ scala compile Conversion.scala --server=false
there was 1 feature warning; re-run with -feature for details
1 warning found
$ scala compile Conversion.scala --server=false -feature
-- Feature Warning: Conversion.scala:8:17
8 |  println(charge(450))
  |                 ^^^
  |Use of implicit conversion given instance given_Conversion_Int_Cents should be enabled
  |by adding the import clause 'import scala.language.implicitConversions'
  |or by setting the compiler option -language:implicitConversions.
  |See the Scala docs for value scala.language.implicitConversions for a discussion
  |why the feature should be explicitly enabled.
1 warning found

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 flags_session.py

Without a flag, the unused value taxPercent passed in silence. -Wunused:all reports it as [E198] Unused Symbol Warning, unused local definition, and with -Werror that warning stops the build. The call to a deprecated method first gave only the summary there was 1 deprecation warning; re-run with -deprecation for details; -deprecation named the method, the version that deprecated it and the message its author left. The implicit conversion behaved the same way: a summary, then with -feature the full warning, which says how to enable the feature on purpose.

Flag What it shows When to use it
-explain the reasoning behind a message, in more words when a message is not clear
-deprecation each use of a deprecated definition, with the version and its author’s note always in CI, and before you upgrade
-feature each use of a language feature that should be enabled explicitly always
-Wunused:all unused imports, local values, parameters and private members in your own projects
-Werror nothing new: it makes every warning an error in CI, once the warnings are fixed

On the command line, Scala CLI passes options that start with -W, and a few common ones such as -deprecation, straight to the compiler; any other compiler option is written after -O. To keep them with the project, write them in project.scala, for example //> using options -deprecation -feature -Wunused:all.

Key idea

Turn on -deprecation, -feature and -Wunused:all from the start, fix what they find, and then add -Werror in CI, so that no warning reaches the main branch.

Checkpoint

Check: Flags that show more

  1. Question 1 of 2 A compile ends with there was 1 deprecation warning; re-run with -deprecation for details. How do you see the warning?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Compile again with -deprecation

    Some warnings arrive as a one-line summary. -deprecation and -feature turn their summaries into full warnings with the place and the advice.

  2. Question 2 of 2 Without any flag, what did the compiler say about the unused value taxPercent?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Nothing at all

    -Wunused:all reports unused imports, local values, parameters and private members as E198 warnings. Without it the compiler says nothing about them.

Look up the code, then fix the first error first

The codes are there to be looked up. The Scala 3 Reference has a page for every code from E001 to E234, each with a sample that triggers it, the compiler’s real output and a fix; E007 is Type Mismatch, E029 Pattern Match Exhaustivity, E171 Missing Argument, E172 Missing Implicit Argument and E198 Unused Symbol. The pages describe the newest compiler, so a message on 3.9.0 can differ in its wording.

When there are several errors, start with the first. The compiler leaves out errors that would only follow from an earlier one, so fixing the first can bring others into view. This receipt has three mistakes, yet its first compile reports one; after that one is fixed, the next compile reports the other two:

kata/Receipt.scala Scala · kata/Receipt.scala
// Fix the build: three mistakes stop this receipt from compiling. Each item is bought twice,
// and the receipt should print: 1140 cents for cake, tea
case class Item(name: String, cents: Long)

def lineTotal(item: Item, quantity: Int): Long = item.cents * quantity

@main def receipt(): Unit =
  val items = List(Item("tea", 250), Item("cake", "320"))
  val total = items.map(i => lineTotal(i)).sum
  val byName = items.sorted
  println(s"$total cents for ${byName.map(_.name).mkString(", ")}")
The receipt before and after its first fix Python · kata_session.py
from session import run

# The receipt as given, then the same file after its first mistake was fixed.
run("""
cd kata
!scala compile . --server=false
cd ../kata-after-first-fix
!scala compile . --server=false
""")

Output

$ cd kata
$ scala compile . --server=false
-- [E007] Type Mismatch Error: Receipt.scala:8:50
8 |  val items = List(Item("tea", 250), Item("cake", "320"))
  |                                                  ^^^^^
  |                                                Found:    ("320" : String)
  |                                                Required: Long
  |
  | longer explanation available when compiling with `-explain`
1 error found
Compilation failed
[exit status 1]
$ cd ../kata-after-first-fix
$ scala compile . --server=false
-- [E171] Type Error: Receipt.scala:9:38
9 |  val total = items.map(i => lineTotal(i)).sum
  |                             ^^^^^^^^^^^^
  |missing argument for parameter quantity of method lineTotal: (item: Item, quantity: Int): Long
-- [E172] Type Error: Receipt.scala:10:27
10 |  val byName = items.sorted
   |                           ^
   |No given instance of type Ordering[B] was found for parameter ord of method sorted in trait StrictOptimizedSeqOps.
   |I found:
   |
   |    scala.math.Ordering.ordered[B](
   |      /* missing */summon[scala.math.Ordering.AsComparable[B]])
   |
   |But no implicit values were found that match type scala.math.Ordering.AsComparable[B]
   |
   |where:    B is a type variable with constraint >: Item
   |.
   |
   |The following import might make progress towards fixing the problem:
   |
   |  import scala.math.Ordered.orderingToOrdered
   |
2 errors found
Compilation failed
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 kata_session.py

The mismatch on line 8 left the type of items in doubt, and the compiler does not report errors that may only follow from an earlier one. Once "320" became 320, items was a list of Item, and both remaining errors appeared at once. Compile after each fix: the messages change as the code does, and the newest ones are the ones that count.

Checkpoint

Check: Codes and the first error

  1. One question The receipt has three mistakes, but its first compile reported only one. After that one was fixed, two errors appeared. Why?

    Choose one answer.

    Show the answer: One question

    Answer: The compiler leaves out errors that may only follow from an earlier one, so fixing the first brought the others into view

    Fix the first error, compile again, and read the new messages. Errors after the first may depend on it, so the list can change with every fix.

Practise: repair the receipt

Copy kata/Receipt.scala into an empty folder and fix the three mistakes so that scala run . prints 1140 cents for cake, tea. Each item is bought twice, and the names come in alphabetical order. Fix the cause of each error, not only its message: the result must be right as well as compile.

First hint: the last two errors are E171 and E172, the same codes as in the session above. lineTotal needs the quantity, and sorted needs to know how to order items; sortBy(_.name) is one way to tell it.

Then check the five ideas of this lesson, from reading one message to fixing the first error first. A wrong answer says exactly what it misses:

Practice that adapts to you

Practise this lesson

14 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 14 In -- [E007] Type Mismatch Error: Mismatch.scala:2:25, what does 2:25 mean?

    Choose one answer.

    Show the answer: Question 1 of 14

    Answer: Line 2, column 25, where the problem starts

    The first line names the code, the kind of problem and the place: file, line and column. Editors turn the place into a link.

  2. Question 2 of 14 What does ("4250" : String) mean in a Found line?

    Choose one answer.

    Show the answer: Question 2 of 14

    Answer: The type of exactly the string "4250", which is a String

    A literal has a type of its own, the type with exactly that value. Here it is ("4250" : String), a String, while the place required a Long.

  3. Question 3 of 14 This line fails with Found: (4250L : Long) and Required: Int. Which change fixes the cause?

    Read the code, then choose one answer.

    val count: Int = 4250L
    Show the answer: Question 3 of 14

    Answer: Write 4250 without the L, or declare count as a Long if it can grow that big

    Found is a Long and Required is an Int. Remove the gap: an Int literal, 4250, or a Long declaration. Read the two lines the same way for every type mismatch.

  4. Question 4 of 14 In the long E172 message for prices.sorted, which line tells you what is missing?

    Choose one answer.

    Show the answer: Question 4 of 14

    Answer: The first, No given instance of type Ordering[B] was found for parameter ord of method sorted

    Read the first line of a long message first: it says what was not found and for which parameter. The rest helps only when the first line is not enough.

  5. Question 5 of 14 Which changes make prices.sorted work, or replace it, for case class Price(cents: Long) and still give the prices in order? Choose every one.

    Choose every answer that is right.

    Show the answer: Question 5 of 14

    Answer:

    • prices.sortBy(_.cents)
    • object Price: given Ordering[Price] = Ordering.by(_.cents)

    Either say how to order where you sort, with sortBy, or give the type an Ordering that every sort finds. A fix that changes the result type only moves the problem.

  6. Question 6 of 14 A method gains a new parameter, and 40 existing calls now fail with E171. Most of them meant the value that was used before. Which change fixes them all and keeps their meaning?

    Choose one answer.

    Show the answer: Question 6 of 14

    Answer: Give the new parameter a default value equal to the old behaviour

    E171 says which parameter is missing. When most calls mean the same value, a default value removes the cause for all of them; when they mean different values, each call needs its argument.

  7. Question 7 of 14 When does the missing Cash case of Fees.scala fail?

    Choose one answer.

    Show the answer: Question 7 of 14

    Answer: At run time, when the match receives Cash

    The run printed two fees and then threw scala.MatchError: Cash. The warning named the value at compile time; the crash happened when the program reached it.

  8. Question 8 of 14 Why could the compiler name Cash as the value that no case covers?

    Choose one answer.

    Show the answer: Question 8 of 14

    Answer: An enum lists all its values, so the compiler can check a match against every one

    For an enum or a sealed type the compiler knows every possible value, so it can tell which ones a match does not cover and name them in the E029 warning.

  9. Question 9 of 14 A teammate silences E029 in feeCents with case _ => 0. Why is that a poor fix?

    Choose one answer.

    Show the answer: Question 9 of 14

    Answer: It also hides the warning for any value added later, which would then cost 0 without a word

    Name each value in its own case. Then a new value added to the enum gets its own warning, and with -Werror the build fails until someone decides its fee.

  10. Question 10 of 14 Which flag reports unused imports, local values and parameters?

    Choose one answer.

    Show the answer: Question 10 of 14

    Answer: -Wunused:all

    -Wunused:all turns on every kind of unused-definition warning. Combined with -Werror, an unused value stops the build.

  11. Question 11 of 14 How do you make every run of a Scala CLI project use -deprecation, -feature and -Wunused:all?

    Choose one answer.

    Show the answer: Question 11 of 14

    Answer: Put //> using options -deprecation -feature -Wunused:all in project.scala

    //> using options in project.scala passes the options to the compiler for every compile of the project: from the command line, in CI and in the editor.

  12. Question 12 of 14 A project compiles with 40 warnings, and the team wants -Werror in CI. What order works?

    Choose one answer.

    Show the answer: Question 12 of 14

    Answer: Fix the warnings first, then switch -Werror on so that the count stays at zero

    Clear the existing warnings, then let -Werror keep the count at zero. The warnings worth keeping, such as E029, then stop a build before they reach a running program.

  13. Question 13 of 14 Where is each Scala 3 error code explained with a sample, the compiler's output and a fix?

    Choose one answer.

    Show the answer: Question 13 of 14

    Answer: In the error codes section of the Scala 3 Reference

    The Scala 3 Reference documents every code, E007 Type Mismatch and E029 Pattern Match Exhaustivity among them, with an example and a fix. Its pages describe the newest compiler, so wording may differ slightly on 3.9.0.

  14. Question 14 of 14 A compile reports 12 errors. Where do you start?

    Choose one answer.

    Show the answer: Question 14 of 14

    Answer: With the first, then compile again and read the new list

    Fix the first error first and compile again. The receipt showed how one fix can make other errors appear, and the same fix can just as well make others disappear.

Interview questions

Fresher · What does -Werror do, and why do teams turn it on in CI?

-Werror makes the compiler treat every warning as an error: a build that would finish with warnings fails instead, with the message No warnings can be incurred under -Werror. Teams turn it on in CI because some warnings predict real bugs. A non-exhaustive match, warning E029, compiles, and the program then throws MatchError on the value the warning named; with -Werror the same code cannot be merged. It also stops warnings from piling up until nobody reads them. It works together with the flags that produce warnings, such as -deprecation, -feature and -Wunused:all. The usual way to adopt it is to fix the existing warnings first, then switch it on in CI so the count stays at zero, and to keep it off while experimenting locally if it gets in the way.

Key takeaways

  • A diagnostic gives a code, the file, line and column, the line with a caret, and for a type error what was found against what was required; their difference is usually the fix.
  • E171 means a missing argument and E172 a missing given instance; fix the cause, for example by giving a type an Ordering, rather than trying the imports the message suggests.
  • A warning such as E029 lets the build pass, and the program can still crash on the value it named; -Werror turns warnings into errors.
  • -deprecation, -feature and -Wunused:all show what the compiler otherwise holds back or sums up in one line, and -explain adds its reasoning.
  • The Scala 3 Reference explains every code from E001 to E234; fix the first error first and compile again, because errors can hide the ones after them.

Terms in this lesson

diagnostic
A message from the compiler about the source: an error, which stops the build, or a warning, which does not. Scala 3 diagnostics carry a code such as E007.
exhaustive match
A match with a case for every possible value of its type. When the compiler finds a value that no case covers, it warns with E029, and that value throws MatchError at run time.
given instance
A value that the compiler passes by itself to a parameter declared with using, chosen by its type. sorted, for example, needs a given Ordering for the element type.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.