diff --git a/license_sh/helpers.py b/license_sh/helpers.py
index b00c499..414d90b 100644
--- a/license_sh/helpers.py
+++ b/license_sh/helpers.py
@@ -67,6 +67,18 @@ def extract_npm_license(json_data, version: str):
     """
     if not json_data:
         return None
+    version_data = json_data.get("versions", {}).get(version, {})
+    licenses_array = version_data.get("licenses")
+    if licenses_array:
+        return get_npm_license_from_licenses_array(licenses_array)
+    license_name = version_data.get("license")
+    if license_name:
+        return (
+            license_name.get("type")
+            if type(license_name) is dict
+            else f"{license_name}"
+        )
+
     licenses_array = json_data.get("licenses")
     if licenses_array:
         return get_npm_license_from_licenses_array(licenses_array)
@@ -79,11 +91,7 @@ def extract_npm_license(json_data, version: str):
             else f"{license_name}"
         )
 
-    version_data = json_data.get("versions", {}).get(version, {})
-    licenses_array = version_data.get("licenses")
-    if licenses_array:
-        return get_npm_license_from_licenses_array(licenses_array)
-    return version_data.get("license", None)
+    return None
 
 
 def flatten_dependency_tree(tree):
@@ -151,9 +159,11 @@ def is_license_ok(license_text, whitelist):
 
 
 def normalize_license_expression(license_text_raw):
-    if license_text_raw is None:
-        return None
-    license_text, normalized = normalize(f"{license_text_raw}")
+    if license_text_raw:
+        data = normalize(f"{license_text_raw}")
+        license_text, normalized = data
+    else:
+        license_text = None
     try:
         license = licensing.parse(license_text)
     except:
diff --git a/license_sh/runners/maven/__init__.py b/license_sh/runners/maven/__init__.py
index 6bdd75a..4ed30e0 100644
--- a/license_sh/runners/maven/__init__.py
+++ b/license_sh/runners/maven/__init__.py
@@ -1,5 +1,4 @@
 import tempfile
-import sys
 from contextlib import nullcontext
 from os import path
 import xml.etree.ElementTree as ET
@@ -68,13 +67,7 @@ def get_dependency_tree_xml(directory: str, debug=False):
             ],
             capture_output=not debug,
         )
-        try:
-            return ET.parse(tmpfile).getroot()
-        except:
-            print(
-                f"Couldn't get data from maven...", file=sys.stderr,
-            )
-            exit(1)
+        return ET.parse(tmpfile).getroot()
 
     return None
 
diff --git a/license_sh/runners/npm/__init__.py b/license_sh/runners/npm/__init__.py
index 8410874..2e1bc40 100644
--- a/license_sh/runners/npm/__init__.py
+++ b/license_sh/runners/npm/__init__.py
@@ -1,5 +1,4 @@
 import json
-import sys
 import subprocess
 from os import path
 from contextlib import nullcontext
@@ -77,11 +76,6 @@ def get_dependency_tree(package_json, package_lock_tree):
 
     # load root dependencies from package.json
     for dep_name in package_json.get("dependencies", {}).keys():
-        if not dep_name in package_lock_tree:
-            print(
-                f"{dep_name} package not found in package-lock.json", file=sys.stderr,
-            )
-            exit(1)
         dependency = package_lock_tree[dep_name]
         version = dependency.get("version")
         parent = AnyNode(
diff --git a/license_sh/runners/yarn/__init__.py b/license_sh/runners/yarn/__init__.py
index 2ed68ac..098b070 100644
--- a/license_sh/runners/yarn/__init__.py
+++ b/license_sh/runners/yarn/__init__.py
@@ -1,6 +1,5 @@
 import json
 import subprocess
-import sys
 from os import path
 from anytree import AnyNode, PreOrderIter
 from typing import Dict, List, Tuple
@@ -278,14 +277,8 @@ def get_dependency_tree(
         resolved_version = package_map.get(
             f"{dep_name}@{dep_version}"
         )  # Resolve locked version of the package
-        full_name = f"{dep_name}@{resolved_version}"
-        if full_name not in flat_tree.keys():
-            print(
-                f"{dep_name} package not found in yarn.lock", file=sys.stderr,
-            )
-            exit(1)
         dependency = flat_tree.get(
-            full_name
+            f"{dep_name}@{resolved_version}"
         )  # Use package full name to get it dependencies
         # Create first level of nodes based on package.json dependencies
         parent = AnyNode(

[NPM] License priority
Version specific license should have priority

https://registry.npmjs.org/foreachasync

3.0.0 - Apache2
Global - (Apache2 or MIT)
diff --git a/tests/runners/test_helpers.py b/tests/test_helpers.py
similarity index 99%
rename from tests/runners/test_helpers.py
rename to tests/test_helpers.py
index 1b168d2..56ef798 100644
--- a/tests/runners/test_helpers.py
+++ b/tests/test_helpers.py
@@ -432,7 +432,7 @@ class NpmRunnerTestCase(unittest.TestCase):
         name = extract_npm_license(data, "1.0.0")
         self.assertEqual(name, "APACHE")
 
-    def test_extract_npm_license_global_priority(self):
+    def test_extract_npm_license_version_priority(self):
         data = json.loads(
             """{
             "name": "name",
@@ -445,7 +445,7 @@ class NpmRunnerTestCase(unittest.TestCase):
         }"""
         )
         name = extract_npm_license(data, "1.0.0")
-        self.assertEqual(name, "MIT")
+        self.assertEqual(name, "APACHE")
 
     def test_extract_npm_license_no_versions(self):
         data = json.loads(

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc pip install pipenv
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aiohappyeyeballs==2.6.1
aiohttp==3.11.14
aiosignal==1.3.2
anytree==2.12.1
async-timeout==5.0.1
attrs==25.3.0
boolean.py==4.0
certifi==2025.1.31
distlib==0.3.9
docopt==0.6.2
exceptiongroup==1.2.2
filelock==3.18.0
frozenlist==1.5.0
idna==3.10
iniconfig==2.1.0
license-expression==30.4.1
-e git+https://github.com/webscopeio/license.sh.git@6e061004a33bafb6b4736dea4dcffd27ce038cb5#egg=license_sh
multidict==6.2.0
packaging==24.2
pipdeptree==2.26.0
pipenv==2024.4.1
platformdirs==4.3.7
pluggy==1.5.0
prompt_toolkit==3.0.50
propcache==0.3.1
pytest==8.3.5
questionary==2.1.0
six==1.17.0
termcolor==2.3.0
tomli==2.2.1
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
wcwidth==0.2.13
yarl==1.18.3
yaspin==3.1.0

name: license.sh
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aiohappyeyeballs==2.6.1
      - aiohttp==3.11.14
      - aiosignal==1.3.2
      - anytree==2.12.1
      - async-timeout==5.0.1
      - attrs==25.3.0
      - boolean-py==4.0
      - certifi==2025.1.31
      - distlib==0.3.9
      - docopt==0.6.2
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - frozenlist==1.5.0
      - idna==3.10
      - iniconfig==2.1.0
      - license-expression==30.4.1
      - multidict==6.2.0
      - packaging==24.2
      - pipdeptree==2.26.0
      - pipenv==2024.4.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - prompt-toolkit==3.0.50
      - propcache==0.3.1
      - pytest==8.3.5
      - questionary==2.1.0
      - six==1.17.0
      - termcolor==2.3.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - wcwidth==0.2.13
      - yarl==1.18.3
      - yaspin==3.1.0
prefix: /opt/conda/envs/license.sh

tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_version_priority
tests/test_helpers.py::NpmRunnerTestCase::test_annotate_dependency_tree tests/test_helpers.py::NpmRunnerTestCase::test_bad_licenses_identified tests/test_helpers.py::NpmRunnerTestCase::test_bad_licenses_identified__one_package_ignored_by_package_whitelist tests/test_helpers.py::NpmRunnerTestCase::test_bad_licenses_identified_are_ignored_by_package_whitelist tests/test_helpers.py::NpmRunnerTestCase::test_dependency_tree_is_flattened tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_None_data tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_None_version tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_from_versions tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_no_version tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_no_version_license tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_no_versions tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_license_simple tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_global_empty tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_global_multiple tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_global_single tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_global_single_string tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_specific_version_multiple tests/test_helpers.py::NpmRunnerTestCase::test_extract_npm_licenses_specific_version_simple tests/test_helpers.py::NpmRunnerTestCase::test_get_npm_license_from_licenses_array_None tests/test_helpers.py::NpmRunnerTestCase::test_get_npm_license_from_licenses_empty tests/test_helpers.py::NpmRunnerTestCase::test_is_license_ok_brackets tests/test_helpers.py::NpmRunnerTestCase::test_is_license_ok_json tests/test_helpers.py::NpmRunnerTestCase::test_is_license_ok_negative tests/test_helpers.py::NpmRunnerTestCase::test_is_license_ok_simple tests/test_helpers.py::NpmRunnerTestCase::test_parse_license_complex tests/test_helpers.py::NpmRunnerTestCase::test_parse_license_simple
license_sh/runners/npm/__init__.py license_sh/runners/maven/__init__.py license_sh/runners/yarn/__init__.py license_sh/helpers.py
license_sh/runners/npm/__init__.py license_sh/runners/maven/__init__.py license_sh/runners/yarn/__init__.py license_sh/helpers.py