You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DownloadErrorFactory.ThrowException (src/Tizen.Content.Download/Tizen.Content.Download/DownloadErrorFactory.cs:58-100) is the single error-to-exception funnel for the whole module. Its switch enumerates 22 DownloadError cases — and has no default branch:
internalstaticvoidThrowException(interrorCode,stringerrorMessage=null,stringparamName=null){
...switch((DownloadError)errorCode){caseDownloadError.InvalidParameter:
...
case DownloadError.IoError:thrownewInvalidOperationException(message);caseDownloadError.NotSupported:thrownewNotSupportedException(message);caseDownloadError.PermissionDenied:thrownewUnauthorizedAccessException(message);}// unmapped code -> falls through and RETURNS NORMALLY}
All 45 call sites in the module (Request.cs 31, CacheManager.cs 8, Notification.cs 6) follow the pattern if (ret != (int)DownloadError.None) DownloadErrorFactory.ThrowException(ret, ...); and rely on the call never returning.
Problem
Silent failure at 45 call sites (bug risk — Coding Guidelines). If the native url_download layer ever returns a code outside the 22 mapped values (a newly added platform error, or a generic Tizen error not aliased into DownloadError), ThrowException returns normally and the caller proceeds as if the interop call succeeded. Concrete consequences: CacheManager.MaxCacheSize returns an uninitialized out value; the Request constructors keep building state on a broken _downloadId; Start() reports success while nothing was started. This is the identical defect class already confirmed in ConnectionErrorFactory.ThrowConnectionException ([AI Refactoring] ConnectionErrorFactory.ThrowConnectionException default 분기 누락 → switch expression 으로 silent failure 차단 [Scope: src/Tizen.Network.Connection] (2026-04-26) #7591).
22-case switch statement with per-case throw (Modernization). The mapping is a pure value-to-exception translation — the canonical shape for a C# 8 switch expression with or patterns, which makes fall-through structurally impossible and cuts the method to a third of its size.
Proposed Improvement
Convert to a throw ... switch expression whose _ arm covers every unmapped code.
Before
switch((DownloadError)errorCode){caseDownloadError.InvalidParameter:caseDownloadError.InvalidUrl:caseDownloadError.InvalidDestination:caseDownloadError.InvalidNetworkType:thrownewArgumentException(message,paramName);caseDownloadError.OutOfMemory:caseDownloadError.NetworkUnreachable:// ... 15 more cases ...caseDownloadError.IoError:thrownewInvalidOperationException(message);caseDownloadError.NotSupported:thrownewNotSupportedException(message);caseDownloadError.PermissionDenied:thrownewUnauthorizedAccessException(message);}
After
internalstaticvoidThrowException(interrorCode,stringerrorMessage=null,stringparamName=null){DownloadErrorerr=(DownloadError)errorCode;stringmessage=String.IsNullOrEmpty(errorMessage)?err.ToString():errorMessage;throwerrswitch{DownloadError.InvalidParameter or DownloadError.InvalidUrl or
DownloadError.InvalidDestination or DownloadError.InvalidNetworkType=>newArgumentException(message,paramName),DownloadError.NotSupported=>newNotSupportedException(message),DownloadError.PermissionDenied=>newUnauthorizedAccessException(message),
_ =>newInvalidOperationException(message),};}
(The 19 codes previously mapped to InvalidOperationException collapse into the _ arm together with all future unmapped codes.)
Call sites exposed to silent fall-through: 45 -> 0 (the method now provably always throws).
Method body: ~30 LOC -> ~12 LOC; case labels 22 -> 6 pattern arms.
Property getters that could return uninitialized out values after a swallowed error: eliminated (e.g. CacheManager.MaxCacheSize, CachePath, Request.DownloadedPath).
API Compatibility Check
Public API signature change: none (internal factory; public surface untouched).
Behavior change: previously-unmapped native error codes now throw InvalidOperationException instead of being silently ignored. This matches the <exception cref="InvalidOperationException"> contract already documented on every public member of the module. All 45 call sites are guarded by ret != None (or pass fixed non-None codes), so no success path ever reaches the throw.
Tizen API Level floor: maintained (switch expression is C# 8 syntax — no new runtime API).
Impact Scope
1 internal method, single assembly. Measured via rg: 45 call sites, all inside src/Tizen.Content.Download (no cross-assembly callers of the internal factory).
[Type: Refactoring]
[Scope: src/Tizen.Content.Download]
[Priority: 🔴 Critical]
[Lens: Coding Guidelines, Modernization]
Observation
DownloadErrorFactory.ThrowException(src/Tizen.Content.Download/Tizen.Content.Download/DownloadErrorFactory.cs:58-100) is the single error-to-exception funnel for the whole module. Itsswitchenumerates 22DownloadErrorcases — and has nodefaultbranch:All 45 call sites in the module (
Request.cs31,CacheManager.cs8,Notification.cs6) follow the patternif (ret != (int)DownloadError.None) DownloadErrorFactory.ThrowException(ret, ...);and rely on the call never returning.Problem
url_downloadlayer ever returns a code outside the 22 mapped values (a newly added platform error, or a generic Tizen error not aliased intoDownloadError),ThrowExceptionreturns normally and the caller proceeds as if the interop call succeeded. Concrete consequences:CacheManager.MaxCacheSizereturns an uninitializedoutvalue; theRequestconstructors keep building state on a broken_downloadId;Start()reports success while nothing was started. This is the identical defect class already confirmed inConnectionErrorFactory.ThrowConnectionException([AI Refactoring] ConnectionErrorFactory.ThrowConnectionException default 분기 누락 → switch expression 으로 silent failure 차단 [Scope: src/Tizen.Network.Connection] (2026-04-26) #7591).switchstatement with per-casethrow(Modernization). The mapping is a pure value-to-exception translation — the canonical shape for a C# 8switchexpression withorpatterns, which makes fall-through structurally impossible and cuts the method to a third of its size.Proposed Improvement
Convert to a
throw ... switchexpression whose_arm covers every unmapped code.Before
After
(The 19 codes previously mapped to
InvalidOperationExceptioncollapse into the_arm together with all future unmapped codes.)Target Files
src/Tizen.Content.Download/Tizen.Content.Download/DownloadErrorFactory.csExpected Impact (Quantitative Metrics)
outvalues after a swallowed error: eliminated (e.g.CacheManager.MaxCacheSize,CachePath,Request.DownloadedPath).API Compatibility Check
InvalidOperationExceptioninstead of being silently ignored. This matches the<exception cref="InvalidOperationException">contract already documented on every public member of the module. All 45 call sites are guarded byret != None(or pass fixed non-None codes), so no success path ever reaches the throw.Impact Scope
src/Tizen.Content.Download(no cross-assembly callers of the internal factory).