@@ -97,6 +97,115 @@ public async Task ValidateQueryNotFoundResponse()
9797 await db . DeleteAsync ( ) ;
9898 }
9999
100+ /// <summary>
101+ /// Validates that 404 with substatus 0 is returned when an item doesn't exist,
102+ /// and 404 with substatus 1003 is returned when the container doesn't exist.
103+ /// This allows disambiguation between item not found vs owner resource (container/database) not found.
104+ /// </summary>
105+ [ TestMethod ]
106+ public async Task ValidateSubStatusCodeForItemNotFoundVsContainerNotFound ( )
107+ {
108+ // Create a test database and container
109+ Database db = await CosmosNotFoundTests . client . CreateDatabaseAsync ( "NotFoundTest" + Guid . NewGuid ( ) . ToString ( ) ) ;
110+ Container container = await db . CreateContainerAsync ( "NotFoundTest" + Guid . NewGuid ( ) . ToString ( ) , "/pk" , 500 ) ;
111+
112+ // Test 1: Item doesn't exist in existing container - should return 404 with substatus 0
113+ ResponseMessage response = await container . ReadItemStreamAsync (
114+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
115+ id : DoesNotExist ) ;
116+
117+ Assert . IsNotNull ( response ) ;
118+ Assert . AreEqual ( HttpStatusCode . NotFound , response . StatusCode ) ;
119+ Assert . AreEqual ( 0 , ( int ) response . Headers . SubStatusCode ,
120+ "SubStatusCode should be 0 when item doesn't exist in an existing container" ) ;
121+
122+ // Test 2: Container doesn't exist - should return 404 with substatus 1003
123+ Container nonExistentContainer = db . GetContainer ( DoesNotExist ) ;
124+ response = await nonExistentContainer . ReadItemStreamAsync (
125+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
126+ id : DoesNotExist ) ;
127+
128+ Assert . IsNotNull ( response ) ;
129+ Assert . AreEqual ( HttpStatusCode . NotFound , response . StatusCode ) ;
130+ Assert . AreEqual ( 1003 , ( int ) response . Headers . SubStatusCode ,
131+ "SubStatusCode should be 1003 when container doesn't exist (owner resource not found)" ) ;
132+
133+ // Test 3: Database doesn't exist - should also return 404 with substatus 1003
134+ Database nonExistentDb = CosmosNotFoundTests . client . GetDatabase ( DoesNotExist ) ;
135+ Container containerInNonExistentDb = nonExistentDb . GetContainer ( DoesNotExist ) ;
136+ response = await containerInNonExistentDb . ReadItemStreamAsync (
137+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
138+ id : DoesNotExist ) ;
139+
140+ Assert . IsNotNull ( response ) ;
141+ Assert . AreEqual ( HttpStatusCode . NotFound , response . StatusCode ) ;
142+ Assert . AreEqual ( 1003 , ( int ) response . Headers . SubStatusCode ,
143+ "SubStatusCode should be 1003 when database doesn't exist (owner resource not found)" ) ;
144+
145+ // Cleanup
146+ await db . DeleteAsync ( ) ;
147+ }
148+
149+ /// <summary>
150+ /// Validates that CosmosException exposes the substatus code when thrown,
151+ /// allowing developers to distinguish between different types of 404 errors.
152+ /// </summary>
153+ [ TestMethod ]
154+ public async Task ValidateCosmosExceptionSubStatusCodeForNotFound ( )
155+ {
156+ // Create a test database and container
157+ Database db = await CosmosNotFoundTests . client . CreateDatabaseAsync ( "NotFoundTest" + Guid . NewGuid ( ) . ToString ( ) ) ;
158+ Container container = await db . CreateContainerAsync ( "NotFoundTest" + Guid . NewGuid ( ) . ToString ( ) , "/pk" , 500 ) ;
159+
160+ // Test 1: Item doesn't exist in existing container - CosmosException should have substatus 0
161+ try
162+ {
163+ ItemResponse < dynamic > response = await container . ReadItemAsync < dynamic > (
164+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
165+ id : DoesNotExist ) ;
166+ Assert . Fail ( "Expected CosmosException to be thrown" ) ;
167+ }
168+ catch ( CosmosException ex ) when ( ex . StatusCode == HttpStatusCode . NotFound )
169+ {
170+ Assert . AreEqual ( 0 , ex . SubStatusCode ,
171+ "SubStatusCode should be 0 when item doesn't exist in an existing container" ) ;
172+ }
173+
174+ // Test 2: Container doesn't exist - CosmosException should have substatus 1003
175+ Container nonExistentContainer = db . GetContainer ( DoesNotExist ) ;
176+ try
177+ {
178+ ItemResponse < dynamic > response = await nonExistentContainer . ReadItemAsync < dynamic > (
179+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
180+ id : DoesNotExist ) ;
181+ Assert . Fail ( "Expected CosmosException to be thrown" ) ;
182+ }
183+ catch ( CosmosException ex ) when ( ex . StatusCode == HttpStatusCode . NotFound )
184+ {
185+ Assert . AreEqual ( 1003 , ex . SubStatusCode ,
186+ "SubStatusCode should be 1003 when container doesn't exist (owner resource not found)" ) ;
187+ }
188+
189+ // Test 3: Database doesn't exist - CosmosException should have substatus 1003
190+ Database nonExistentDb = CosmosNotFoundTests . client . GetDatabase ( DoesNotExist ) ;
191+ Container containerInNonExistentDb = nonExistentDb . GetContainer ( DoesNotExist ) ;
192+ try
193+ {
194+ ItemResponse < dynamic > response = await containerInNonExistentDb . ReadItemAsync < dynamic > (
195+ partitionKey : new Cosmos . PartitionKey ( DoesNotExist ) ,
196+ id : DoesNotExist ) ;
197+ Assert . Fail ( "Expected CosmosException to be thrown" ) ;
198+ }
199+ catch ( CosmosException ex ) when ( ex . StatusCode == HttpStatusCode . NotFound )
200+ {
201+ Assert . AreEqual ( 1003 , ex . SubStatusCode ,
202+ "SubStatusCode should be 1003 when database doesn't exist (owner resource not found)" ) ;
203+ }
204+
205+ // Cleanup
206+ await db . DeleteAsync ( ) ;
207+ }
208+
100209 private async Task ContainerOperations ( Database database , bool dbNotExist )
101210 {
102211 // Create should fail if the database does not exist
0 commit comments