← Debugging Guides

阅读中文版本

Spring Could Not Resolve Placeholder — Missing Property

Fix Spring "Could not resolve placeholder" by adding the missing property, checking profile-specific files, and verifying the property source order.

intermediatedebuggingjavaspringconfiguration

Symptoms

  • ApplicationContext fails with "Could not resolve placeholder 'x' in value \"${x}\""
  • Works with the dev profile but fails in prod
  • The property exists in a file that is not being loaded

Possible causes

  • The property is missing from the active profile or environment
  • A profile-specific file such as application-prod.properties is not on the classpath
  • A default value was not provided for an optional @Value

Diagnosis steps

Read the exact placeholder name

java -jar app.jar 2>&1 | grep -A 2 "Could not resolve placeholder"

Interpretation

The message names the unresolved key, which tells you which property to add.

Inspect the active profiles and property sources

java -jar app.jar --debug 2>&1 | grep -A 20 "PropertySourcesPlaceholder"

Interpretation

The debug log lists loaded property sources and profiles, revealing where the value should come from.

Root cause

Spring resolves ${...} placeholders against the active environment at bean creation. If no property source, profile file, or environment variable supplies the key and no default is given, resolution fails and the context aborts.

Fix

Add the property to the correct profile file, pass it as an environment variable, or supply a default with @Value("${x:default}"); verify which profiles are active in each environment.

Risk note

Defaults can mask missing production config; prefer failing fast for required values and defaulting only genuinely optional ones.

Verify the fix

Start the application with the target profile and confirm the context loads; log the resolved value (redacted) to prove the property source is correct.

Symptoms

This debugging guide addresses “Spring Could Not Resolve Placeholder — Missing Property”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.

Observed symptoms include:

  • ApplicationContext fails with “Could not resolve placeholder ‘x’ in value "${x}"”
  • Works with the dev profile but fails in prod
  • The property exists in a file that is not being loaded

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Read the exact placeholder name

java -jar app.jar 2>&1 | grep -A 2 "Could not resolve placeholder"

The message names the unresolved key, which tells you which property to add.

Step 2: Inspect the active profiles and property sources

java -jar app.jar --debug 2>&1 | grep -A 20 "PropertySourcesPlaceholder"

The debug log lists loaded property sources and profiles, revealing where the value should come from.

Likely contributors, in order of frequency:

  • The property is missing from the active profile or environment
  • A profile-specific file such as application-prod.properties is not on the classpath
  • A default value was not provided for an optional @Value

Root Cause

Spring resolves ${…} placeholders against the active environment at bean creation. If no property source, profile file, or environment variable supplies the key and no default is given, resolution fails and the context aborts.

The Fix

Add the property to the correct profile file, pass it as an environment variable, or supply a default with @Value(“${x:default}”); verify which profiles are active in each environment.

Watch out: Defaults can mask missing production config; prefer failing fast for required values and defaulting only genuinely optional ones.

@Service
public class MailService {
    // required -> fail fast if absent
    @Value("${mail.host}")
    private String host;

    // optional -> explicit default
    @Value("${mail.port:587}")
    private int port;
}

# application-prod.properties
mail.host=smtp.example.com

Verify and Prevent

Start the application with the target profile and confirm the context loads; log the resolved value (redacted) to prove the property source is correct.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.