Modern applications often span Spring-based backends, SQL and NoSQL databases, reactive programming, mobile platforms, and browser storage. Each layer introduces its own failure modes — and many bugs only appear when these layers interact.
This article presents real production-level issues, explains why they happen, and shows correct implementation and testing patterns.
1. SQL Server: Dropping Columns That Are Still Referenced
Symptom
ALTER TABLE bank_user DROP COLUMN authorization_code;
Fails with:
The index 'Missing_IxNC_bank_user_user_id_E3636' is dependent on column 'authorization_code'
Why This Happens
SQL Server auto-generates indexes (often named Missing_IxNC_*) based on query plans.
These indexes are real objects, even if you didn’t create them explicitly.
How to Identify Dependencies
SELECT
i.name AS index_name,
c.name AS column_name
FROM sys.indexes i
JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE c.name = 'authorization_code';
Correct Migration Flow
DROP INDEX Missing_IxNC_bank_user_user_id_E3636 ON bank_user;
ALTER TABLE bank_user DROP COLUMN authorization_code;
Liquibase Best Practice
<changeSet id="drop-auth-code" author="dev">
<dropIndex indexName="Missing_IxNC_bank_user_user_id_E3636"
tableName="bank_user"/>
<dropColumn tableName="bank_user" columnName="authorization_code"/>
</changeSet>
✔ Never drop columns blindly in production
2. Spring JPA @Entity vs Liquibase Drift
Problem
Entities evolve, but database schema lags behind.
@Entity
@Table(name = "bank_user")
public class BankUser {
@Column(name = "user_id")
private Long userId;
// column removed in code
// private String authorizationCode;
}
But DB column still exists.
Why This Is Dangerous
- Hibernate validates entities, not schema history
- Liquibase does not auto-diff entities
- Runtime failures appear late
Safe Workflow
- Validate schema on startup:
spring.jpa.hibernate.ddl-auto=validate
- Use Liquibase diff only between DBs, not entities:
liquibase diff \
--referenceUrl=jdbc:h2:mem:ref \
--url=jdbc:postgresql://prod-db
- Treat entities as read-only contracts, not schema authorities.
3. Cassandra UDT Runtime Failures
Symptom
udtValue.get("other", Other.class);
Throws:
IllegalArgumentException: other is not a field defined in this UDT
Root Cause
Cassandra UDTs are schema-defined, not dynamic.
Your Java model assumes a field that does not exist in Cassandra.
Verify UDT Definition
SELECT type_name, field_names
FROM system_schema.types
WHERE keyspace_name = 'app';
Safe Access Pattern
UserDefinedType type = udtValue.getType();
if (type.getFieldNames().contains("other")) {
account.setOther(udtValue.get("other", Other.class));
}
Defensive Mapping Rule
✔ Never assume UDT structure
✔ Validate fields before access
✔ Fail fast during startup if schemas mismatch
4. Reactive + Blocking Code: ClassCastException Hell
Symptom
ClassCastException: GenericResponse cannot be cast to List
The Code That Causes It
List<Account> accounts =
monitoring.monitorCall(
() -> connector.refreshAccounts(cid).block()
);
Where:
Mono<GenericResponse<List<Account>>> refreshAccounts(...)
The Mistake
.block() returns GenericResponse, not List.
Correct Pattern
GenericResponse<List<Account>> response =
connector.refreshAccounts(cid)
.block(Duration.ofSeconds(10));
List<Account> accounts = response.getData();
Mockito Mock (Correct)
when(connector.refreshAccounts(any()))
.thenReturn(
Mono.just(
new GenericResponse<List<Account>>()
.withData(Collections.emptyList())
)
);
✔ Mock exact return types
✔ Never cast around reactive wrappers
5. Mocking Void Methods with Lambdas
Symptom
no instance(s) of type variable(s) T exist so that void conforms to T
The Problematic Mock
when(monitoring.writeDataMicroMeter(any(), any(), any(), any()))
.thenReturn(...)
But method signature is:
void writeDataMicroMeter(Runnable r, ...)
Correct Mockito Pattern
doAnswer(invocation -> {
Runnable r = invocation.getArgument(0);
r.run();
return null;
}).when(monitoring)
.writeDataMicroMeter(any(), any(), any(), any());
✔ when() is for non-void
✔ doAnswer() is for void side-effects
6. WebSQL Is Dead — IndexedDB Migration
Deprecated Code
window.openDatabase(...)
Why It Breaks
- WebSQL removed from Chrome
- No future support
- No transactional guarantees
IndexedDB Correct Pattern
const request = indexedDB.open(DB_NAME, 1);
request.onupgradeneeded = e => {
const db = e.target.result;
db.createObjectStore('records', { keyPath: 'id' });
};
request.onsuccess = e => {
const db = e.target.result;
const tx = db.transaction('records', 'readwrite');
const store = tx.objectStore('records');
store.put({ id: 1, value: 'data' });
};
Common Error
db.transaction is not a function
➡ Happens when db is not IDBDatabase
➡ Usually due to incorrect promise resolution
7. iOS AVFoundation Capture Failures
Error
AVFoundationErrorDomain Code=-11800
Root Causes
- Missing permissions
- Camera already in use
- Invalid capture session state
Mandatory Permissions
<key>NSCameraUsageDescription</key>
<string>Camera access required</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access required</string>
Defensive Setup
guard AVCaptureDevice.authorizationStatus(for: .video) == .authorized else {
return
}
✔ Always test on real devices
8. PHP Blank Page = Fatal Error Hidden
Classic Issue
<?php require_once 'dbconnect.php'; ?>
Page renders blank.
Root Cause
- PHP errors hidden in production
- MySQL connection fails silently
Enable Debugging (Temporary)
ini_set('display_errors', 1);
error_reporting(E_ALL);
MySQL Access Error
Access denied for user 'user'@'localhost'
✔ In cPanel:
- DB user ≠ system user
- Host is often not
localhost - Privileges must be assigned explicitly
9. ISO DateTime Validation
Invalid
2024-0225T11:49:12.000
Valid ISO-8601
YYYY-MM-DDTHH:mm:ss.SSS
2024-02-25T11:49:12.000
Java Validation
Instant.parse("2024-02-25T11:49:12.000Z");
Final Engineering Lessons
✔ Schemas are contracts, not suggestions
✔ Reactive ≠ blocking — be explicit
✔ Mock signatures must match exactly
✔ Platform APIs age — plan migrations
✔ Validate assumptions early, not in production

