Skip to content
TaeyoungKim.dev

Spring @RequestParam defaultValue: Why missing limit becomes 10 but abc returns 400

Java/SpringWritten 3 min readTaeyoungKim
LinkedInX

Omit limit from a list API request and the default 10 works. Send limit=abc and the server returns 400. These are different cases: Spring distinguishes no usable value from a supplied value that cannot be converted to an integer.

Add this controller to a Spring Boot web app. Its response reports the limit actually applied to /items:

When does @RequestParam use the default value?

java
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

@RestController
class ItemController {
    @GetMapping("/items")
    Map<String, Integer> items(
            @RequestParam(name = "limit", defaultValue = "10") int limit) {
        if (limit < 1 || limit > 31) {
            throw new ResponseStatusException(
                    HttpStatus.BAD_REQUEST, "limit must be between 1 and 31");
        }
        return Map.of("limit", limit);
    }
}

@RequestParam looks for limit. If it is missing or empty, as in ?limit=, Spring substitutes "10" and converts it to the method's int type. Specifying a default also implies required=false. The Spring @RequestParam API documents both rules.

The diagram follows three failure stages: an absent value gets the default, abc fails integer conversion, and 99 converts successfully but fails the explicit 1..31 range check.

?limit=3 has a value, so Spring passes 3. The default 10 is a value to use only when none was supplied, not a maximum allowed value.

Why does limit=abc return 400 instead of 10?

abc is not empty. Spring therefore tries to convert it to int rather than using the default. Conversion fails before the controller body runs. Spring MVC's default exception handling maps that type mismatch to HTTP 400; see its default exception resolver.

defaultValue does not silently repair a malformed input. Replacing every typo with 10 would hide a client-side mistake.

Is limit=99 the same kind of failure?

No. 99 converts to an integer, then fails the example's separate 1..31 check. Remove that check and defaultValue="10" alone would not reject 99.

RequestValue reaching the methodResult
/itemsDefault 10200, {"limit":10}
/items?limit=Default 10200, {"limit":10}
/items?limit=33200, {"limit":3}
/items?limit=abcConversion fails first400
/items?limit=9999, then range check fails400

Whether a real API rejects 99 or caps it at 31 is part of its contract. Define that separately from the default, especially when the limit controls database work or response size.

Which cases should a test cover?

Use MockMvc to check missing, empty, valid numeric, malformed numeric, and out-of-range values separately. Decide whether to assert exact error wording after the team has defined its error response format.

Key takeaways

@RequestParam(defaultValue="10") supplies 10 when limit is missing or empty. abc is present but fails integer conversion. 99 converts, then fails the example's separate range validation. Diagnose failures by stage: absence, conversion, or range.

Author

TaeyoungKim

Connecting technical foundations with implementation, verification, and production decisions.

#Spring#Spring MVC#RequestParam#defaultValue#Query parameter#HTTP 400

Read next