Nosmai / docs
Nosmai Effects Nosmai Moderation Nosmai Try-ons coming soon
Docs menu Errors and troubleshooting
docs / nosmai effects / reference / errors and troubleshooting

Errors and troubleshooting

The SDK's error types and codes, what they mean, and how to fix common integration issues.

Overview

Nosmai operations can fail because of application configuration, device state, permissions, network access, an invalid filter package, or an incorrect camera lifecycle.

A production integration should:

  1. check every asynchronous result
  2. keep technical details out of user-facing messages
  3. retry only temporary failures
  4. avoid retry loops for invalid configuration
  5. release the camera when a screen closes
  6. record enough context to reproduce a failure
  7. never record a complete license key

The exact error shape differs by platform:

PlatformMain error form
AndroidExceptions and callback error strings
iOSNSError with NosmaiErrorDomain and NosmaiErrorCode
FlutterNosmaiError with NosmaiErrorType, code, message, and optional details

Handle an operation in this order:

Start operation
    |
    v
Check immediate validation
    |
    v
Wait for asynchronous result
    |
    +---- success ----> update the interface
    |
    +---- failure ----> classify the error
                           |
                           +---- temporary ----> offer retry
                           |
                           +---- permission ----> explain required access
                           |
                           +---- configuration -> stop and fix configuration

Do not update a selected filter button before the apply completion reports success.

Initialization failures

Common initialization problems:

ProblemMeaningAction
Empty license keyThe application supplied no usable keyFix application configuration
Invalid keyThe key does not exist, was revoked, or is incompleteCheck the full key in the Nosmai Console
Package mismatchThe key belongs to a different Android package name or iOS bundle identifierRegister and use the final application identifier
Platform mismatchAn Android key is used on iOS, or an iOS key is used on AndroidUse the key issued for that platform
Expired licenseThe license is no longer activeRenew or replace the license
Unsupported SDK versionThe installed SDK version is not accepted by the license serviceUpdate to a supported release
First launch offlineNo valid local license exists and the server cannot be reachedConnect the device and retry
Incorrect device timeThe verification timestamp cannot be trustedEnable automatic date and time
Monthly usage limitThe project reached its active-device allowanceReview the project plan

Initialization should have one application-level owner. Starting it from several screens can produce confusing state and duplicate work.

License error codes

The native license service can report these stable codes:

CodeMeaningRetry
LICENSE_EXPIREDThe license or subscription expiredNo, renew first
API_KEY_INVALIDThe key is invalid, incomplete, or revokedNo, fix the key
PACKAGE_ID_MISMATCHThe key does not match the installed application identifierNo, fix project configuration
PLATFORM_MISMATCHThe key belongs to another platformNo, use the correct key
SDK_VERSION_UNSUPPORTEDThe installed SDK version is not supportedNo, update the SDK
MAU_LIMIT_EXCEEDEDThe monthly active-device limit was reachedNo, review the plan
DEVICE_NOT_REGISTEREDThe device is not accepted by the license configurationNo, review the project
TIMESTAMP_INVALIDDevice date or time is incorrectAfter fixing device time
TOO_MANY_REQUESTSToo many verification requests were sentYes, with delay
MISSING_FIELDSRequired verification information was not availableNo, review integration
NETWORK_ERRORThe license server could not be reachedYes, when connectivity returns
INTERNAL_ERRORVerification could not complete because of a local or server errorYes, once, then report

Do not show these technical codes directly to an end user. Map them to a short explanation and a suitable action.

Network failures

License verification and cloud filter operations need network access. Camera frames and active local effects do not need to be uploaded for normal processing.

Common network conditions:

ConditionTypical symptomAction
DNS failureHostname cannot be resolvedCheck internet, DNS, VPN, and private DNS settings
Connection failureServer cannot be reachedCheck firewall, proxy, VPN, and device network
TimeoutRequest took too longRetry with delay
TLS failureSecure connection could not be verifiedCheck device time, certificates, proxy, and network inspection
Rate limitToo many requestsApply increasing retry delays
Interrupted transferResponse ended before completionRetry when the network is stable

For example, cURL code 6 on Android means the device could not resolve the server hostname. It is a DNS or connectivity issue, not a camera or filter-rendering failure.

Retry policy

Use a bounded retry:

Attempt 1: immediately
Attempt 2: after 1 second
Attempt 3: after 3 seconds
Attempt 4: after 8 seconds
Then stop and wait for user action or a network-state change

Do not continuously retry invalid keys, package mismatches, expired licenses, or unsupported SDK versions.

Android error handling

Initialization

Android initialization validates required arguments immediately:

try {
    NosmaiSDK.initialize(
        getApplicationContext(),
        BuildConfig.NOSMAI_LICENSE_KEY
    );
} catch (IllegalArgumentException error) {
    // Context or license key is missing.
} catch (RuntimeException error) {
    // Native SDK initialization could not start.
}

NosmaiSDK.isInitialized() confirms that the Android API was initialized:

if (!NosmaiSDK.isInitialized()) {
    // Do not open the camera screen.
}

This state does not replace asynchronous license-status handling inside the SDK. A temporary network failure can still be reported while the SDK evaluates a valid local license.

Filter apply

Always use the callback:

NosmaiEffects.applyEffect(
    filterPath,
    new NosmaiEffects.EffectCallback() {
        @Override
        public void onSuccess() {
            // Update selected filter state.
        }

        @Override
        public void onError(String errorMessage) {
            // Keep the previous selected state and report the failure.
        }
    }
);

Android callback errors are descriptive strings. Do not parse them as a permanent numeric error contract. Use them for diagnostics and show a stable application message to the user.

Direct camera input errors

Listen for direct-input failures:

previewView.addOnOesInputErrorListener(reason -> {
    // Stop the current Camera2 session.
    // Reconnect using the normal Camera2 frame-input fallback.
});

A direct-input error should switch to the sample application's supported fallback. It should not leave the user on a black preview.

Recording

NosmaiSDK.startRecording(
    previewView,
    outputPath,
    new NosmaiSDK.RecordingCallback() {
        @Override
        public void onStarted(
            boolean success,
            String error
        ) {
            if (!success) {
                // Re-enable the record button.
            }
        }
    }
);

When stopping, wait for finalization:

NosmaiSDK.stopRecording(
    new NosmaiSDK.RecordingCallback() {
        @Override
        public void onCompleted(
            String outputPath,
            boolean success,
            String error
        ) {
            if (!success) {
                // Do not publish an incomplete file.
            }
        }
    }
);

iOS error handling

Public error codes

iOS uses NosmaiErrorDomain with these NosmaiErrorCode values:

ValueConstantMeaning
1000NosmaiErrorCodeUnknownAn unclassified failure
1001NosmaiErrorCodeLicenseInvalidThe license was rejected
1002NosmaiErrorCodeLicenseExpiredThe license expired
1003NosmaiErrorCodeNetworkErrorA required network request failed
1004NosmaiErrorCodeCameraPermissionDeniedCamera permission was denied
1005NosmaiErrorCodeCameraNotAvailableThe camera is unavailable
1006NosmaiErrorCodeEffectLoadFailedA filter or effect could not load
1007NosmaiErrorCodeInitializationFailedSDK initialization failed
1008NosmaiErrorCodeResourceNotFoundA required file was not found
1009NosmaiErrorCodeInvalidParameterA method received an invalid value
1010NosmaiErrorCodeMemoryErrorRequired memory could not be allocated
403NosmaiErrorCodeFeatureNotEnabledThe license does not include the requested feature

Initialization

[[NosmaiCore shared]
    initializeWithAPIKey:licenseKey
              completion:^(BOOL success, NSError *error) {
        if (success) {
            return;
        }

        if ([error.domain isEqualToString:NosmaiErrorDomain]) {
            switch ((NosmaiErrorCode)error.code) {
                case NosmaiErrorCodeNetworkError:
                    // Offer retry when connectivity returns.
                    break;

                case NosmaiErrorCodeLicenseInvalid:
                case NosmaiErrorCodeLicenseExpired:
                    // Stop and review the license.
                    break;

                default:
                    // Record error.localizedDescription.
                    break;
            }
        }
    }];

Delegates

Set delegates after initialization:

NosmaiCore *core = [NosmaiCore shared];
core.delegate = self;
core.camera.delegate = self;
core.effects.delegate = self;

Receive general failures:

- (void)nosmaiDidFailWithError:(NSError *)error {
    // Record the error domain, code, and safe context.
}

Receive camera failures:

- (void)nosmaiCameraDidFailWithError:(NSError *)error {
    // Stop capture and show a retry or permission action.
}

Receive effect failures:

- (void)nosmaiEffectDidFailWithError:(NSError *)error
                           forEffect:(NSString *)effectID {
    // Keep the previous selected effect state.
}

License status

The iOS delegate can report:

  • VALID
  • INVALID
  • EXPIRED
  • UNVERIFIED
- (void)nosmaiDidChangeLicenseStatus:(BOOL)isValid
                              status:(NSString *)status {
    if ([status isEqualToString:@"UNVERIFIED"]) {
        // Wait for verification or a valid local-license decision.
    }
}

UNVERIFIED is not the same as a definitive invalid license. It can occur while verification is pending or temporarily unavailable.

Flutter error handling

Flutter exposes NosmaiError:

class NosmaiError {
  final NosmaiErrorType type;
  final String code;
  final String message;
  final String? details;
}

Catch operation errors

try {
  final applied =
      await NosmaiFlutter.instance.applyEffect(filter.path);

  if (!applied) {
    // The package was not applied.
  }
} on NosmaiError catch (error) {
  final message = error.userMessage;
  final canRetry = error.isRecoverable;

  // Present message and offer retry only when appropriate.
}

Listen for native errors

StreamSubscription<NosmaiError>? errorSubscription;

void startErrorListener() {
  errorSubscription =
      NosmaiFlutter.instance.onError.listen((error) {
    // Record error.type, error.code, and error.details.
  });
}

Cancel the listener:

await errorSubscription?.cancel();

Flutter error types

TypeMeaning
unknownAn unclassified failure
stateErrorThe requested action is not valid in the current state
operationTimeoutThe operation exceeded its allowed time
platformErrorThe Android or iOS call failed
networkErrorA network request failed
invalidParameterA method received an invalid value
sdkNotInitializedA method was called before initialization
invalidLicenseThe license was rejected
licenseExpiredThe license expired
cameraPermissionDeniedCamera access was denied
cameraUnavailableThe camera cannot be opened
cameraConfigurationFailedThe camera configuration was rejected
cameraSwitchFailedFront or back camera switch failed
filterNotFoundThe filter file does not exist
filterInvalidFormatThe filter package is not valid
filterLoadFailedThe filter package could not be loaded
filterDownloadFailedA cloud filter download failed
recordingPermissionDeniedRequired recording permission was denied
recordingStorageFullThe device has insufficient free storage
recordingWriteFailedThe output file could not be written
recordingInProgressAnother recording is already active

Preview errors

NosmaiCameraPreview(
  onInitialized: () {
    // Enable camera controls.
  },
  onError: (error) {
    // Show a retry or permission message.
  },
)

The preview error callback reports camera-view startup and resume failures. It does not replace onError, which can also report filter, license, network, and recording failures.

Camera permission problems

Permission denied

When permission is denied:

  1. stop the loading indicator
  2. explain why camera access is required
  3. show a retry action if the system can ask again
  4. show an application-settings action after permanent denial
  5. keep non-camera screens usable

Do not repeatedly trigger the system permission dialog without a user action.

Camera unavailable

The camera can be unavailable when:

  • another application is using it
  • another camera library in the same application owns it
  • the previous camera screen did not release it
  • the device is transitioning between foreground and background
  • the camera service has temporarily failed

Stop every previous camera owner before retrying.

Black preview

Use this order:

  1. confirm initialization succeeded
  2. confirm camera permission is granted
  3. confirm the preview has a non-zero size
  4. confirm only one camera source is active
  5. confirm the old camera closed before a switch
  6. confirm the previous screen released its camera
  7. confirm the app returned to the foreground
  8. remove all active effects and test the plain preview

Android

Check:

  • NosmaiSDK.startProcessing(previewView) was called
  • Camera2 starts after the preview is ready
  • the camera sends the correct size and orientation
  • a direct-input error activates the normal Camera2 fallback
  • cameraHelper.stopCamera() runs when leaving the screen

iOS

Check:

  • initialization completion reported success
  • attachToView: was called
  • the view has a valid frame
  • startCapture returned YES
  • no other AVCaptureSession owns the camera
  • the old view was detached before attaching a new one

Flutter

Check:

  • NosmaiFlutter.initialize returned true
  • only one NosmaiCameraPreview is mounted
  • global cleanup is not running while a new preview is created
  • the previous platform view finished disposal
  • the preview widget has a valid size

Camera switching problems

Symptoms include:

  • preview becomes black
  • front camera works but back camera does not
  • both cameras stop after switching back
  • effect orientation becomes incorrect

Correct behavior:

  1. ignore repeated switch taps while a switch is active
  2. stop or reconfigure the old camera
  3. wait for the new camera source
  4. update front or back camera state
  5. update mirroring once
  6. resume effects after frames arrive

Do not open the new camera while the old Camera2 or AVFoundation session is still closing.

Orientation and mirroring problems

SymptomLikely cause
Preview is sidewaysCamera sensor rotation was not converted to display orientation
Preview is upside downRotation direction is reversed
Front preview is not mirroredFront preview mirror was not enabled
Face effect moves in the opposite horizontal directionThe frame and preview use different mirror rules
Effect is correct but recorded video is reversedPreview and output mirroring were treated as the same setting

Apply horizontal mirroring in one place. A double mirror can make the preview appear correct while face landmarks and effects use the wrong direction.

Filter does not load

Check:

  1. the file path exists
  2. the filename ends in .nosmai
  3. the package is complete and was not modified after creation
  4. the package supports the installed SDK version
  5. the license includes the required feature
  6. the apply completion or callback reports success
  7. the package type is one of the supported types

Supported package types:

  • filter
  • effect
  • beauty_effect
  • background

Use applyEffect for all four types. Do not choose a lower-level apply method based on a guessed package type.

Local filter is missing from the list

Production discovery requires:

filter_name.nosmai
filter_name_manifest.json
filter_name_preview.png

The base name must match.

Check that:

  • all three files are present
  • the manifest JSON is valid
  • the manifest type is supported
  • the folder is included in the application bundle
  • Flutter declares the folder in pubspec.yaml
  • the local filter cache was refreshed after adding files

Use debug discovery for loose development packages. Do not use it as the production catalog.

Filter appears in the wrong category

The package manifest controls its category.

Intended behaviorManifest type
Full-frame color or LUT filterfilter
AR mask, sticker, particle, or 3D effecteffect
Packaged makeup or face beauty effectbeauty_effect
Packaged background effectbackground

Fix the package manifest. Do not relabel the returned item only in application UI.

Effect disappears or replaces another effect

Some external packages share the same active category.

Expected examples:

  • applying a new regular filter replaces the previous regular filter
  • applying a new effect replaces the previous AR or beauty package
  • applying a beauty_effect replaces the previous AR or beauty package
  • a regular filter can remain active with an AR effect

Read active state after applying a package. Do not assume every package can remain active with every other package.

Face effect is delayed or unstable

Check:

  • the preview remains close to the target frame rate
  • the face is large enough and reasonably lit
  • the camera frame orientation is correct
  • frame timestamps increase normally
  • the app is not doing expensive work on the main thread
  • recording or streaming is not exceeding the device's capacity
  • only visible features remain active

Do not solve tracking delay by skipping an uncontrolled number of face updates. A stale face result can make makeup detach during movement.

Background replacement problems

Nothing changes

Confirm that:

  • advanced effects are included in the license
  • the background method returned success where available
  • image data is valid
  • a video path is an accessible local file
  • the device supports the required processing

Edge quality is poor

Test:

  • even lighting
  • visible separation between subject and background
  • a supported camera resolution
  • lower motion
  • a simpler set of active effects

Hair and motion boundaries are more difficult than static clothing and wall boundaries.

Cloud filter problems

Catalog is empty

Check:

  • cloud filters are enabled for the license
  • the device has internet access
  • the requested category is valid
  • the requested compatibility version is supported
  • pagination is not requesting a page beyond the final page

Cloud category values are:

  • effects
  • filter
  • bg
  • beauty_effect

Download fails

Check:

  • filter ID is not empty
  • network access remains available
  • the device has free storage
  • the application can write to its cache or files directory
  • the item is still available in the catalog

Do not apply a cloud item until the download result provides a valid local path.

Recording problems

Recording does not start

Check:

  • camera preview is already active
  • no previous recording is starting, active, or stopping
  • microphone permission is granted when audio is required
  • the output location is writable
  • the device has free storage

Recording stops but no file is available

Wait for the stop completion. Video finalization can continue briefly after the user taps stop.

Do not:

  • close the camera screen before finalization
  • upload the file before success
  • start another recording while stop is pending
  • delete or move the output path early

Application freezes

Common causes:

  • blocking the main thread for every frame
  • waiting synchronously for camera or graphics work
  • applying many filters without waiting for the previous operation
  • starting several downloads or decodes at once
  • repeatedly creating and destroying the camera preview
  • recording and streaming above the device's sustainable resolution

Actions:

  1. reproduce without active effects
  2. add one feature at a time
  3. measure preview frame rate
  4. inspect main-thread work
  5. test without recording or streaming
  6. test on another supported device
  7. capture a system trace if the freeze remains

Native crashes

Examples include:

  • UnsatisfiedLinkError on Android
  • SIGSEGV in a native library
  • graphics errors followed by process termination
  • release-only crashes after code shrinking

Android UnsatisfiedLinkError

This normally means Java and native code do not match.

Check:

  • the AAR comes from one SDK release
  • no older SDK classes are copied into the app
  • the final package includes lib/arm64-v8a/libnosmai.so
  • the device is arm64-v8a
  • code shrinking kept required JNI methods
  • the application does not package two different Nosmai native libraries

Native graphics crash

Collect:

  • complete crash stack
  • device model and Android or iOS version
  • SDK version
  • camera position
  • active filter names and types
  • actions immediately before the crash
  • whether recording or streaming was active

Do not hide a repeatable native crash behind an automatic restart. Report the reproducible sequence.

Performance troubleshooting

Use this isolation order:

  1. plain preview
  2. one regular color filter
  3. one face-tracked effect
  4. built-in beauty
  5. makeup
  6. background replacement
  7. recording
  8. live streaming

Record frame rate and device temperature at each step.

Common improvements:

  • target a stable 30 FPS
  • keep one camera preview active
  • avoid invisible active effects
  • use the recommended direct Android camera input with its device fallback
  • reduce recording or streaming resolution on slower devices
  • avoid large uncompressed filter textures
  • prevent repeated filter changes while one apply is still running
  • pause the camera when the app is not visible

Lifecycle troubleshooting

Camera indicator remains on

The camera source was not stopped.

  • Android: stop Camera2 when the activity or fragment leaves the screen
  • iOS: call stopCapture and detachFromView
  • Flutter: remove NosmaiCameraPreview and allow its native view to dispose

Camera does not return

The old view may still own the camera, or global cleanup may overlap the new screen.

Use:

  • pause and resume for temporary backgrounding
  • stop and detach when leaving a camera screen
  • full cleanup only when the application is finished with the SDK

Do not call full cleanup from every Flutter widget dispose method.

Logging

iOS

Enable SDK debug logging during investigation:

[[NosmaiCore shared] setDebugLoggingEnabled:YES];

Disable it for release:

[[NosmaiCore shared] setDebugLoggingEnabled:NO];

Android

Use Android Studio Logcat and filter by application package and Nosmai-related tags. The current public Android API does not expose the same logging toggle as iOS.

Flutter

Capture:

  • Dart exceptions
  • NosmaiFlutter.instance.onError
  • Android Logcat when testing Android
  • Xcode console when testing iOS

Flutter logs alone may not include the native cause of a camera or graphics failure.

Protect sensitive information

Before sharing logs:

  • remove the complete Nosmai license key
  • remove access tokens
  • remove private live-stream channel tokens
  • remove user identifiers
  • review local file paths for personal information

Keep:

  • SDK version
  • application version
  • platform and OS version
  • device model
  • error domain, code, and message
  • filter type and non-sensitive filter identifier
  • reproducible steps

Support report checklist

Include:

  1. platform
  2. device model
  3. OS version
  4. application version
  5. Nosmai SDK or Flutter package version
  6. debug or release build
  7. front or back camera
  8. active filter types
  9. whether recording or streaming was active
  10. exact reproduction steps
  11. complete relevant error or native crash stack
  12. result without active filters

Do not send only a screenshot of the final frame when reporting a crash or freeze. Include the logs and the action sequence that produced it.

Nosmai

We make advanced camera and AI technology accessible to every developer. By packaging hard problems into simple

developers
legal
newsletter

Product updates and release notes. No spam.

© 2026 nosmai, inc · all rights reserved