Skip to content

[Android][Impeller/Vulkan][vector_graphics / flutter_svg] — Rendering corruption and crashes after upgrading to Flutter 3.35.4 #177380

Closed

Description

@ziii08

Overview

After upgrading from Flutter 3.24.0 to Flutter 3.35.4, several previously working SVG assets now render incorrectly or cause crashes on specific Android devices. On Flutter 3.24.0, all SVGs displayed properly without corruption. However, on 3.35.4, certain SVGs become broken, while others cause the app to crash silently (no log output). This issue is particularly severe on Redmi Note 11, where displaying large or complex SVG/VG assets leads to consistent crashes.

Steps to reproduce

  1. Use the same SVG/VG assets that rendered fine in Flutter 3.24.0.
  2. Upgrade the project to Flutter 3.35.4.
  3. Display the assets in a simple widget tree, such as a GridView or ListView with multiple vector items.
  4. Run on Redmi Note 11 with Impeller enabled.

Result:

  • App crashes or assets render broken.
  • Disabling Impeller (--no-enable-impeller) prevents crashes but does not fully fix rendering corruption.

Expected results

  • SVG and VG assets should render correctly and consistently across Flutter versions.
  • Rendering should not crash on any supported Android device when using Impeller.
  • Visual output should remain identical across all devices and GPU vendors, ensuring consistent rendering quality regardless of hardware differences.

Actual results

  • Many SVG/VG assets appear broken or fail to render on Flutter 3.35.4.
  • Crashes occur silently (no log output) on specific devices, especially Redmi Note 11.
  • Performance lag is noticeable when rendering multiple vector assets.

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:vector_graphics/vector_graphics.dart';

void main() => runApp(const CompareApp());

class CompareApp extends StatelessWidget {
  const CompareApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const ComparePage(),
      theme: ThemeData(useMaterial3: true),
    );
  }
}

class ComparePage extends StatelessWidget {
  const ComparePage({super.key});

  @override
  Widget build(BuildContext context) {
    final items = const [
      ('env_dog1.svg', _Renderer.svg),
      ('env_dog1.vg.bin', _Renderer.vg),
      ('rectangle_4433.svg', _Renderer.svg),
      ('rectangle_4433.vg.bin', _Renderer.vg),
    ];

    return Scaffold(
      appBar: AppBar(
        title: const Text('SVG vs VG comparison'),
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(36),
          child: Padding(
            padding: const EdgeInsets.only(bottom: 8.0),
            child: Text(
              'Run with:  flutter run --enable-impeller   and   --no-enable-impeller',
              style: Theme.of(context).textTheme.labelSmall,
            ),
          ),
        ),
      ),
      body: GridView.builder(
        padding: const EdgeInsets.all(16),
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2,
          mainAxisSpacing: 16,
          crossAxisSpacing: 16,
          childAspectRatio: 1,
        ),
        itemCount: items.length,
        itemBuilder: (_, i) {
          final (path, type) = items[i];
          return _VectorTile(path: 'assets/$path', type: type);
        },
      ),
    );
  }
}

enum _Renderer { svg, vg }

class _VectorTile extends StatelessWidget {
  const _VectorTile({required this.path, required this.type});
  final String path;
  final _Renderer type;

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 1,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      child: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Expanded(
              child: Center(
                child: AspectRatio(
                  aspectRatio: 1,
                  child: switch (type) {
                    _Renderer.svg => SvgPicture.asset(
                      path,
                      width: 220,
                      height: 220,
                      fit: BoxFit.contain,
                      clipBehavior: Clip.none,
                      placeholderBuilder: (_) => const CircularProgressIndicator(),
                      errorBuilder: (_, __, ___) => const DecoratedBox(
                        decoration: BoxDecoration(color: Color(0x11000000)),
                        child: Center(child: Text('SVG error')),
                      ),
                    ),
                    _Renderer.vg => VectorGraphic(
                      loader: AssetBytesLoader(path),
                      width: 220,
                      height: 220,
                      clipViewBox: false,
                    ),
                  },
                ),
              ),
            ),
            const SizedBox(height: 8),
            Text(
              path.split('/').last,
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
              style: Theme.of(context).textTheme.labelMedium,
            ),
            Text(
              type.name.toUpperCase(),
              style: Theme.of(context).textTheme.labelSmall,
            ),
          ],
        ),
      ),
    );
  }
}

Sample Assets
svg_vg_repro_assets.zip

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

No response

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.35.4, on Microsoft Windows [Version 10.0.26100.6899], locale en-ID) [510ms]
    • Flutter version 3.35.4 on channel stable at D:\src\flutter\fvm\versions\3.35.4
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision d693b4b9db (5 weeks ago), 2025-09-16 14:27:41 +0000
    • Engine revision c298091351
    • Dart version 3.9.2
    • DevTools version 2.48.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations,
      enable-lldb-debugging

[✓] Windows Version (11 Home Single Language 64-bit, 24H2, 2009) [1,577ms]

[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [3.1s]
    • Android SDK at D:\src\android\Sdk
    • Emulator version 35.4.9.0 (build_id 13025442) (CL:N/A)
    • Platform android-36, build-tools 36.0.0
    • Java binary at: D:\src\Apps\Android\jbr\bin\java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 17.0.11+0--11852314)
    • All Android licenses accepted.

[✓] Chrome - develop for the web [170ms]
    • Chrome at C:\Users\HP\AppData\Local\Google\Chrome\Application\chrome.exe

[✓] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.11) [168ms]
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.14.36401.2
    • Windows 10 SDK version 10.0.26100.0

[✓] Android Studio (version 2024.1) [52ms]
    • Android Studio at D:\src\Apps\Android
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • android-studio-dir = D:\src\Apps\Android
    • Java version OpenJDK Runtime Environment (build 17.0.11+0--11852314)

[✓] IntelliJ IDEA Community Edition (version 2023.2) [49ms]
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin version 232.9559.10

[✓] VS Code (version 1.105.1) [15ms]
    • VS Code at C:\Users\HP\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.120.0

[✓] Connected device (4 available) [756ms]
    • 2201117TY (mobile) • ac548bae • android-arm64  • Android 13 (API 33)
    • Windows (desktop)  • windows  • windows-x64    • Microsoft Windows [Version 10.0.26100.6899]
    • Chrome (web)       • chrome   • web-javascript • Google Chrome 141.0.7390.122
    • Edge (web)         • edge     • web-javascript • Microsoft Edge 141.0.3537.71

[✓] Network resources [690ms]
    • All expected network resources are available.

• No issues found!

Activity

  1. added
    in triagePresently being triaged by the triage team
    on Oct 23, 2025
  2. huycozy commented on Oct 23, 2025

    @huycozy
    Member

    Thanks for the report. I'm also able to reproduce the issue on the latest Flutter stable and master channels. Tested on Realme 6, Android 11.

    package versions
      flutter_svg:
        dependency: "direct main"
        description:
          name: flutter_svg
          sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678
          url: "https://pub.dev"
        source: hosted
        version: "2.2.1"
      vector_graphics:
        dependency: "direct main"
        description:
          name: vector_graphics
          sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
          url: "https://pub.dev"
        source: hosted
        version: "1.1.19"
      vector_graphics_codec:
        dependency: transitive
        description:
          name: vector_graphics_codec
          sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
          url: "https://pub.dev"
        source: hosted
        version: "1.1.13"
      vector_graphics_compiler:
        dependency: transitive
        description:
          name: vector_graphics_compiler
          sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc
          url: "https://pub.dev"
        source: hosted
        version: "1.1.19"
    
    Flutter versions (stable and master)
    [✓] Flutter (Channel stable, 3.35.6, on macOS 26.0 25A354 darwin-arm64, locale en-US) [794ms]
        • Flutter version 3.35.6 on channel stable at /Users/huym4/Documents/WORKING/SDK/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 9f455d2486 (11 days ago), 2025-10-08 14:55:31 -0500
        • Engine revision d2913632a4
        • Dart version 3.9.2
        • DevTools version 2.48.0
        • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-lldb-debugging
    [!] Flutter (Channel master, 3.38.0-1.0.pre-200, on macOS 26.0 25A354 darwin-arm64, locale en-US) [2.2s]
        • Flutter version 3.38.0-1.0.pre-200 on channel master at /Users/huym4/Documents/WORKING/SDK/flutter_master
        ! Warning: `flutter` on your path resolves to /Users/huym4/Documents/WORKING/SDK/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huym4/Documents/WORKING/SDK/flutter_master. Consider adding /Users/huym4/Documents/WORKING/SDK/flutter_master/bin to the front of your path.
        ! Warning: `dart` on your path resolves to /Users/huym4/Documents/WORKING/SDK/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huym4/Documents/WORKING/SDK/flutter_master. Consider adding /Users/huym4/Documents/WORKING/SDK/flutter_master/bin to the front of your path.
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 1a3a81888c (74 minutes ago), 2025-10-22 22:14:18 -0400
        • Engine revision 1a3a81888c
        • Dart version 3.11.0 (build 3.11.0-49.0.dev)
        • DevTools version 2.51.0
        • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, omit-legacy-version-file, enable-lldb-debugging
        • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
  3. added
    platform-androidAndroid applications specifically
    engineflutter/engine related. See also e: labels.
    packageflutter/packages repository. See also p: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    c: fatal crashCrashes that terminate the process
    e: impellerImpeller rendering backend issues and features requests
    p: flutter_svgThe Flutter SVG drawing packages
    and removed
    in triagePresently being triaged by the triage team
    on Oct 23, 2025
  4. jason-simmons commented on Oct 23, 2025

    @jason-simmons
    Member

    Reproduced this on a Samsung Galaxy A02s (Adreno 506 GPU) using the Impeller Vulkan back end.

    The app renders as expected with the GLES back end.

    The Vulkan back end will submit hundreds of command buffers while rendering the assets in this app. While this is happening, the MemAvailable value in /proc/meminfo continually decreases.

    The Android low memory killer daemon will eventually kill the app process when available memory goes below a threshold.

  5. 4 remaining items

  6. chinmaygarde commented on Oct 27, 2025

    @chinmaygarde
    Contributor

    As a policy, I think we should try to avoid rescuing Vulkan support using increasingly egregious workarounds. Our GLES backend is easier to reason about on older devices. We should document the consequences of removing the WorkaroundsVK::input_attachment_self_dependency_broken and attempt to remove it and favor the OpenGL fallback.

  7. added
    P1High-priority issues at the top of the work list
    on Oct 27, 2025
  8. added
    r: fixedIssue is closed as already fixed in a newer version
    on Oct 31, 2025
  9. ziii08 commented on Oct 31, 2025

    @ziii08
    Author

    Thanks for the Vulkan fallback fix — it works perfectly on my Redmi Note 11 (Adreno 610).

    SVG rendering is now smooth and stable (no lag or crash). However, a few SVG assets still appear visually broken under Impeller-OpenGL ES — these rendered fine on Flutter 3.24.0, so it seems to be a rendering difference with Impeller.

    I also noticed that the app can still crash when rendering some VG assets. Unlike before, there are now several driver logs printed right before the crash. I’ve attached the output below for reference:

    log output
    Launching lib\main.dart on 2201117TY in debug mode...
    √ Built build\app\outputs\flutter-apk\app-debug.apk
    D/FlutterJNI(  768): Beginning load of flutter...
    D/FlutterJNI(  768): flutter (null) was loaded normally!
    I/flutter (  768): [IMPORTANT:flutter/shell/platform/android/android_context_vk_impeller.cc(62)] Using the Impeller rendering backend (Vulkan).
    I/flutter (  768): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES).
    W/Looper  (  768): PerfMonitor longMsg : seq=9 plan=13:29:08.575 late=2698ms wall=1638ms h=android.view.Choreographer$FrameHandler c=android.view.Choreographer$FrameDisplayEventReceiver procState=-1
    W/Looper  (  768): PerfMonitor doFrame : time=1638ms vsyncFrame=0 latency=2698ms procState=-1 historyMsgCount=6 (msgIndex=1 wall=533ms seq=3 late=26ms h=android.app.ActivityThread$H w=110) (msgIndex=2 wall=2661ms seq=4 late=549ms h=android.app.ActivityThread$H w=159)
    I/Choreographer(  768): Skipped 93 frames!  The application may be doing too much work on its main thread.
    D/SurfaceView(  768): UPDATE Surface(name=SurfaceView[com.example.svg_vg_converter/com.example.svg_vg_converter.MainActivity])/@0xe09488f, mIsProjectionMode = false
    W/Looper  (  768): PerfMonitor doFrame : time=2ms vsyncFrame=0 latency=1566ms procState=-1 historyMsgCount=5 (msgIndex=1 wall=1638ms seq=9 late=2698ms h=android.view.Choreographer$FrameHandler c=android.view.Choreographer$FrameDisplayEventReceiver)
    Connecting to VM Service at ws://127.0.0.1:49699/h3WjGVvIJck=/ws
    Connected to the VM Service.
    E/libboost(  768): fail to open file: No such file or directory
    E/libboost(  768): fail to open node: No such file or directory
    I/Choreographer(  768): Skipped 160 frames!  The application may be doing too much work on its main thread.
    W/Looper  (  768): PerfMonitor doFrame : time=1ms vsyncFrame=0 latency=2681ms procState=-1 historyMsgCount=1
    D/ProfileInstaller(  768): Installing profile for com.example.svg_vg_converter
    D/DecorView[](  768): getWindowModeFromSystem  windowmode is 1
    D/DecorView[](  768): updateDecorCaptionStatus windowMode is 1
    D/VRI[MainActivity](  768): vri.reportNextDraw android.view.ViewRootImpl.performTraversals:4013 android.view.ViewRootImpl.doTraversal:2725 android.view.ViewRootImpl$TraversalRunnable.run:9812 android.view.Choreographer$CallbackRecord.run:1505 android.view.Choreographer$CallbackRecord.run:1513
    D/VRI[MainActivity](  768): vri.Setup new sync id=0 syncSeqId=0
    D/vg_vg_converter(  768): MiuiProcessManagerServiceStub setSchedFifo
    I/MiuiProcessManagerImpl(  768): setSchedFifo pid:768, mode:3
    I/vg_vg_converter(  768): Background concurrent copying GC freed 14MB AllocSpace bytes, 4(228KB) LOS objects, 49% free, 2832KB/5664KB, paused 90us,32us total 129.305ms
    E/perf_hint(  768): Session creation failed, mPreferredRateNanos: -1
    D/VRI[MainActivity](  768): vri.reportDrawFinished syncSeqId=0 android.view.ViewRootImpl.lambda$createSyncIfNeeded$4$android-view-ViewRootImpl:4081 android.view.ViewRootImpl$$ExternalSyntheticLambda2.run:6 android.os.Handler.handleCallback:942 android.os.Handler.dispatchMessage:99 android.os.Looper.loopOnce:211
    D/DecorView[](  768): onWindowFocusChanged hasWindowFocus true
    I/HandWritingStubImpl(  768): refreshLastKeyboardType: 1
    I/HandWritingStubImpl(  768): getCurrentKeyboardType: 1
    I/HandWritingStubImpl(  768): getCurrentKeyboardType: 1
    W/MirrorManager(  768): this model don't Support
    W/OnBackInvokedCallback(  768): OnBackInvokedCallback is not enabled for the application.
    W/OnBackInvokedCallback(  768): Set 'android:enableOnBackInvokedCallback="true"' in the application manifest.
    I/flutter (  768): Found 77 SVG files in assets/pet/
    I/flutter (  768): Created 77 pairs total
    I/flutter (  768): VG files found: 77
    I/flutter (  768): Found 71 SVG files in assets/pet/
    I/flutter (  768): Created 71 pairs total
    I/flutter (  768): VG files found: 71
    E/Fence   (  768): waitForever: Throttling EGL Production: fence 128 didn't signal in 3000 ms
    E/Fence   (  768):  ----- Printing sync-points under fence fd:128 status:1 name:kgsl-timeline-kgsl-3d0_20-vg_vg -----
    E/Fence   (  768): status:1 driver:kgsl-timeline obj:kgsl-3d0_20-vg_vg_converter(768
    I/Fence   (  768): waitForever: fence(kgsl-timeline-kgsl-3d0_20-vg_vg) status(1)
    I/Fence   (  768): waitForever: sync point: timeline(kgsl-3d0_20-vg_vg_converter(768) drv(kgsl-timeline) status(1) timestamp(118856.867691)
    W/Adreno-GSL(  768): <gsl_ldd_control:553>: ioctl fd 108 code 0xc040094a (IOCTL_KGSL_GPU_COMMAND) failed: errno 35 Resource deadlock would occur
    W/Adreno-GSL(  768): <log_gpu_snapshot:462>: panel.gpuSnapshotPath is not set.not generating user snapshot
    W/Adreno-GSL(  768): <gsl_ldd_control:553>: ioctl fd 108 code 0xc040094a (IOCTL_KGSL_GPU_COMMAND) failed: errno 35 Resource deadlock would occur
    W/Adreno-GSL(  768): <log_gpu_snapshot:462>: panel.gpuSnapshotPath is not set.not generating user snapshot
    Lost connection to device.
    
    Exited.

    Flutter Doctor output

    Doctor output
    [√] Flutter (Channel master, 3.38.0-1.0.pre-331, on Microsoft Windows [Version 10.0.26100.6899], locale en-ID) [5.8s]
        • Flutter version 3.38.0-1.0.pre-331 on channel master at D:\src\flutter\fvm\versions\master
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 6af38a904a (6 hours ago), 2025-10-30 20:48:25 -0400
        • Engine revision 6af38a904a
        • Dart version 3.11.0 (build 3.11.0-81.0.dev)
        • DevTools version 2.51.0
        • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations,   
          enable-native-assets, omit-legacy-version-file, enable-lldb-debugging
    
    [√] Windows Version (11 Home Single Language 64-bit, 24H2, 2009) [2.6s]
    
    [√] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [4.8s]
        • Android SDK at D:\src\android\Sdk
        • Emulator version 35.4.9.0 (build_id 13025442) (CL:N/A)
        • Platform android-36, build-tools 36.0.0
        • Java binary at: D:\src\Apps\Android\jbr\bin\java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 17.0.11+0--11852314)
        • All Android licenses accepted.
    
    [√] Chrome - develop for the web [187ms]
        • Chrome at C:\Users\HP\AppData\Local\Google\Chrome\Application\chrome.exe
    
    [√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.11) [185ms]
        • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
        • Visual Studio Community 2022 version 17.14.36401.2
        • Windows 10 SDK version 10.0.26100.0
    
    [√] Connected device (4 available) [974ms]
        • 2201117TY (mobile) • ac548bae • android-arm64  • Android 13 (API 33)
        • Windows (desktop)  • windows  • windows-x64    • Microsoft Windows [Version 10.0.26100.6899]
        • Chrome (web)       • chrome   • web-javascript • Google Chrome 141.0.7390.123
        • Edge (web)         • edge     • web-javascript • Microsoft Edge 141.0.3537.99
    
    [√] Network resources [887ms]
        • All expected network resources are available.
    
    • No issues found!

    Let me know if a new issue would be better — happy to provide repro assets or an APK.

  10. jason-simmons commented on Oct 31, 2025

    @jason-simmons
    Member

    Please file a new issue with the assets that reproduce the problem.

  11. ziii08 commented on Nov 1, 2025

    @ziii08
    Author

    I’ve opened a follow-up issue with detailed reproduction steps, test assets, and video recordings:
    👉 #177873

    The new report covers SVG and VG rendering results across different GPUs
    Please let me know if there’s anything else I can check or provide.

  12. github-actions commented on Nov 15, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  13. locked as resolved and limited conversation to collaborators on Nov 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work listc: fatal crashCrashes that terminate the processc: regressionIt was better in the past than it is nowe: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.found in release: 3.35Found to occur in 3.35found in release: 3.38Found to occur in 3.38has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: flutter_svgThe Flutter SVG drawing packagesp: vector_graphicsThe vector_graphics package setpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions