diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml
index 42f67e6..c952291 100644
--- a/.github/workflows/check-dist.yml
+++ b/.github/workflows/check-dist.yml
@@ -1,9 +1,3 @@
-# `dist/index.js` is a special file in Actions.
-# When you reference an action with `uses:` in a workflow,
-# `index.js` is the code that will run.
-# For our project, we generate this file through a build process
-# from other source files.
-# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
 name: Check dist/
 
 on:
@@ -18,33 +12,6 @@ on:
   workflow_dispatch:
 
 jobs:
-  check-dist:
-    runs-on: ubuntu-latest
-
-    steps:
-      - uses: actions/checkout@v3
-      - name: Setup Node.js 16.x
-        uses: actions/setup-node@v3
-        with:
-          node-version: 16.x
-          cache: npm
-      - name: Install dependencies
-        run: npm ci
-      - name: Rebuild the dist/ directory
-        run: npm run build
-
-      - name: Compare the expected and actual dist/ directories
-        run: |
-          if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
-            echo "Detected uncommitted changes after build.  See status below:"
-            git diff
-            exit 1
-          fi
-        id: diff
-
-      # If index.js was different than expected, upload the expected version as an artifact
-      - uses: actions/upload-artifact@v3
-        if: ${{ failure() && steps.diff.conclusion == 'failure' }}
-        with:
-          name: dist
-          path: dist/
+  call-check-dist:
+    name: Check dist/
+    uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
diff --git a/.github/workflows/assign-issue.yml b/.github/workflows/issue-opened-workflow.yml
similarity index 78%
rename from .github/workflows/assign-issue.yml
rename to .github/workflows/issue-opened-workflow.yml
index 185eb1d..b127d98 100644
--- a/.github/workflows/assign-issue.yml
+++ b/.github/workflows/issue-opened-workflow.yml
@@ -14,3 +14,9 @@ jobs:
     - name: add_assignees
       run: |
         curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/repos/${{github.repository}}/issues/${{ github.event.issue.number}}/assignees -d '{"assignees":["${{steps.oncall.outputs.CURRENT}}"]}'
+
+    - uses: actions/add-to-project@v0.4.0
+      name: Add to Project Board
+      with:
+        project-url: https://github.com/orgs/actions/projects/12                       
+        github-token: ${{ secrets.CACHE_BOARD_TOKEN }}
diff --git a/.github/workflows/licensed.yml b/.github/workflows/licensed.yml
index 04af62a..37f1560 100644
--- a/.github/workflows/licensed.yml
+++ b/.github/workflows/licensed.yml
@@ -7,18 +7,9 @@ on:
   pull_request:
     branches:
       - main
+  workflow_dispatch:
 
 jobs:
-  test:
-    runs-on: ubuntu-latest
-    name: Check licenses
-    steps:
-      - uses: actions/checkout@v3
-      - run: npm ci
-      - name: Install licensed
-        run: |
-          cd $RUNNER_TEMP
-          curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
-          sudo tar -xzf licensed.tar.gz
-          sudo mv licensed /usr/local/bin/licensed
-      - run: licensed status
+  call-licensed:
+    name: Licensed
+    uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
diff --git a/.github/workflows/add-reviewer-pr.yml b/.github/workflows/pr-opened-workflow.yml
similarity index 83%
rename from .github/workflows/add-reviewer-pr.yml
rename to .github/workflows/pr-opened-workflow.yml
index 3346d9e..cdd375a 100644
--- a/.github/workflows/add-reviewer-pr.yml
+++ b/.github/workflows/pr-opened-workflow.yml
@@ -18,3 +18,9 @@ jobs:
     - name: Add Assignee
       run: |
         curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/repos/${{github.repository}}/issues/${{ github.event.pull_request.number}}/assignees -d '{"assignees":["${{steps.oncall.outputs.CURRENT}}"]}'    
+
+    - uses: actions/add-to-project@v0.4.0
+      name: Add to Project Board
+      with:
+        project-url: https://github.com/orgs/actions/projects/12                       
+        github-token: ${{ secrets.CACHE_BOARD_TOKEN }}
diff --git a/.licenses/npm/@azure/abort-controller.dep.yml b/.licenses/npm/@azure/abort-controller.dep.yml
index f303d5c..b19b8f7 100644
--- a/.licenses/npm/@azure/abort-controller.dep.yml
+++ b/.licenses/npm/@azure/abort-controller.dep.yml
@@ -1,9 +1,9 @@
 ---
 name: "@azure/abort-controller"
-version: 1.0.4
+version: 1.1.0
 type: npm
 summary: Microsoft Azure SDK for JavaScript - Aborter
-homepage: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md
+homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
 license: mit
 licenses:
 - sources: LICENSE
diff --git a/.licenses/npm/@types/node.dep.yml b/.licenses/npm/@types/node.dep.yml
index 18549f3..65dc483 100644
--- a/.licenses/npm/@types/node.dep.yml
+++ b/.licenses/npm/@types/node.dep.yml
@@ -1,6 +1,6 @@
 ---
 name: "@types/node"
-version: 16.11.33
+version: 16.18.3
 type: npm
 summary: TypeScript definitions for Node.js
 homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node
diff --git a/.licenses/npm/minimatch.dep.yml b/.licenses/npm/minimatch.dep.yml
index 317e4bc..a4ff623 100644
--- a/.licenses/npm/minimatch.dep.yml
+++ b/.licenses/npm/minimatch.dep.yml
@@ -1,9 +1,9 @@
 ---
 name: minimatch
-version: 3.0.4
+version: 3.1.2
 type: npm
 summary: a glob matcher in javascript
-homepage: https://github.com/isaacs/minimatch#readme
+homepage: 
 license: isc
 licenses:
 - sources: LICENSE
diff --git a/README.md b/README.md
index 9dd6aec..2890242 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,7 @@ See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/ac
 * Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 60 minutes.
 * Two new actions available for granular control over caches - [restore](restore/action.yml) and [save](save/action.yml)
 * Support cross-os caching as an opt-in feature. See [Cross OS caching](./tips-and-workarounds.md#cross-os-cache) for more info.
+* Added option to fail job on cache miss. See [Exit workflow on cache miss](./restore/README.md#exit-workflow-on-cache-miss) for more info.
 
 Refer [here](https://github.com/actions/cache/blob/v2/README.md) for previous versions
 
@@ -49,6 +50,7 @@ If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are requir
 * `key` - An explicit key for restoring and saving the cache. Refer [creating a cache key](#creating-a-cache-key).
 * `restore-keys` - An ordered list of prefix-matched keys to use for restoring stale cache if no cache hit occurred for key.
 * `enableCrossOsArchive` - An optional boolean when enabled, allows Windows runners to save or restore caches that can be restored or saved respectively on other platforms. Default: false
+* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: false
 * `lookup-only` - Skip downloading cache. Only check if cache entry exists. Default: false
 
 #### Environment Variables
@@ -118,7 +120,7 @@ jobs:
 
     - name: Restore cached Primes
       id: cache-primes-restore
-    - uses: actions/cache/restore@v3
+      uses: actions/cache/restore@v3
       with:
         path: |
           path/to/dependencies
@@ -129,7 +131,7 @@ jobs:
     .
     - name: Save Primes
       id: cache-primes-save
-    - uses: actions/cache/save@v3
+      uses: actions/cache/save@v3
       with:
         path: |
           path/to/dependencies
diff --git a/RELEASES.md b/RELEASES.md
index 428d9ec..50cfd91 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -66,4 +66,7 @@
 
 ### 3.2.3
 - Support cross os caching on Windows as an opt-in feature.
-- Fix issue with symlink restoration on Windows for cross-os caches.
\ No newline at end of file
+- Fix issue with symlink restoration on Windows for cross-os caches.
+
+### 3.2.4
+- Added option to fail job on cache miss.
diff --git a/__tests__/restore.test.ts b/__tests__/restore.test.ts
index 20a4390..4e133d3 100644
--- a/__tests__/restore.test.ts
+++ b/__tests__/restore.test.ts
@@ -226,6 +226,137 @@ test("restore with cache found for restore key", async () => {
     expect(failedMock).toHaveBeenCalledTimes(0);
 });
 
+test("Fail restore when fail on cache miss is enabled and primary + restore keys not found", async () => {
+    const path = "node_modules";
+    const key = "node-test";
+    const restoreKey = "node-";
+    testUtils.setInputs({
+        path: path,
+        key,
+        restoreKeys: [restoreKey],
+        failOnCacheMiss: true
+    });
+
+    const failedMock = jest.spyOn(core, "setFailed");
+    const stateMock = jest.spyOn(core, "saveState");
+    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const restoreCacheMock = jest
+        .spyOn(cache, "restoreCache")
+        .mockImplementationOnce(() => {
+            return Promise.resolve(undefined);
+        });
+
+    await run();
+
+    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
+    expect(restoreCacheMock).toHaveBeenCalledWith(
+        [path],
+        key,
+        [restoreKey],
+        {
+            lookupOnly: false
+        },
+        false
+    );
+
+    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
+    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(0);
+
+    expect(failedMock).toHaveBeenCalledWith(
+        `Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${key}`
+    );
+    expect(failedMock).toHaveBeenCalledTimes(1);
+});
+
+test("restore when fail on cache miss is enabled and primary key doesn't match restored key", async () => {
+    const path = "node_modules";
+    const key = "node-test";
+    const restoreKey = "node-";
+    testUtils.setInputs({
+        path: path,
+        key,
+        restoreKeys: [restoreKey],
+        failOnCacheMiss: true
+    });
+
+    const infoMock = jest.spyOn(core, "info");
+    const failedMock = jest.spyOn(core, "setFailed");
+    const stateMock = jest.spyOn(core, "saveState");
+    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const restoreCacheMock = jest
+        .spyOn(cache, "restoreCache")
+        .mockImplementationOnce(() => {
+            return Promise.resolve(restoreKey);
+        });
+
+    await run();
+
+    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
+    expect(restoreCacheMock).toHaveBeenCalledWith(
+        [path],
+        key,
+        [restoreKey],
+        {
+            lookupOnly: false
+        },
+        false
+    );
+
+    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
+    expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
+    expect(stateMock).toHaveBeenCalledTimes(2);
+
+    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
+    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+
+    expect(infoMock).toHaveBeenCalledWith(
+        `Cache restored from key: ${restoreKey}`
+    );
+    expect(failedMock).toHaveBeenCalledTimes(0);
+});
+
+test("restore with fail on cache miss disabled and no cache found", async () => {
+    const path = "node_modules";
+    const key = "node-test";
+    const restoreKey = "node-";
+    testUtils.setInputs({
+        path: path,
+        key,
+        restoreKeys: [restoreKey],
+        failOnCacheMiss: false
+    });
+
+    const infoMock = jest.spyOn(core, "info");
+    const failedMock = jest.spyOn(core, "setFailed");
+    const stateMock = jest.spyOn(core, "saveState");
+    const restoreCacheMock = jest
+        .spyOn(cache, "restoreCache")
+        .mockImplementationOnce(() => {
+            return Promise.resolve(undefined);
+        });
+
+    await run();
+
+    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
+    expect(restoreCacheMock).toHaveBeenCalledWith(
+        [path],
+        key,
+        [restoreKey],
+        {
+            lookupOnly: false
+        },
+        false
+    );
+
+    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
+    expect(stateMock).toHaveBeenCalledTimes(1);
+
+    expect(infoMock).toHaveBeenCalledWith(
+        `Cache not found for input keys: ${key}, ${restoreKey}`
+    );
+    expect(failedMock).toHaveBeenCalledTimes(0);
+});
+
 test("restore with dry-run set", async () => {
     const path = "node_modules";
     const key = "node-test";
diff --git a/action.yml b/action.yml
index 8ce0593..1eb19b9 100644
--- a/action.yml
+++ b/action.yml
@@ -18,6 +18,10 @@ inputs:
     description: 'An optional boolean when enabled, allows windows runners to save or restore caches that can be restored or saved respectively on other platforms'
     default: 'false'
     required: false
+  fail-on-cache-miss:
+    description: 'Fail the workflow if cache entry is not found'
+    default: 'false'
+    required: false
   lookup-only:
     description: 'Skip downloading cache. Only check if cache entry exists'
     default: 'false'
diff --git a/caching-strategies.md b/caching-strategies.md
index 007d113..87926ed 100644
--- a/caching-strategies.md
+++ b/caching-strategies.md
@@ -182,7 +182,7 @@ steps:
 
 ### Reusing primary key from restore cache as input to save action
 
-If you want to avoid re-computing the cache key again in `save` action, the outputs from `restore` action can be used as input to the `restore` action.
+If you want to avoid re-computing the cache key again in `save` action, the outputs from `restore` action can be used as input to the `save` action.
 
 ```yaml
   - uses: actions/cache/restore@v3
diff --git a/dist/restore-only/index.js b/dist/restore-only/index.js
index 563a519..beaea1f 100644
--- a/dist/restore-only/index.js
+++ b/dist/restore-only/index.js
@@ -4979,6 +4979,7 @@ var Inputs;
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
     Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
+    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
     Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
@@ -50505,9 +50506,13 @@ function restoreImpl(stateProvider) {
                 required: true
             });
             const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
+            const failOnCacheMiss = utils.getInputAsBool(constants_1.Inputs.FailOnCacheMiss);
             const lookupOnly = utils.getInputAsBool(constants_1.Inputs.LookupOnly);
             const cacheKey = yield cache.restoreCache(cachePaths, primaryKey, restoreKeys, { lookupOnly: lookupOnly }, enableCrossOsArchive);
             if (!cacheKey) {
+                if (failOnCacheMiss) {
+                    throw new Error(`Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${primaryKey}`);
+                }
                 core.info(`Cache not found for input keys: ${[
                     primaryKey,
                     ...restoreKeys
diff --git a/dist/restore/index.js b/dist/restore/index.js
index 4bc80fd..774c860 100644
--- a/dist/restore/index.js
+++ b/dist/restore/index.js
@@ -4979,6 +4979,7 @@ var Inputs;
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
     Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
+    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
     Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
@@ -50505,9 +50506,13 @@ function restoreImpl(stateProvider) {
                 required: true
             });
             const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
+            const failOnCacheMiss = utils.getInputAsBool(constants_1.Inputs.FailOnCacheMiss);
             const lookupOnly = utils.getInputAsBool(constants_1.Inputs.LookupOnly);
             const cacheKey = yield cache.restoreCache(cachePaths, primaryKey, restoreKeys, { lookupOnly: lookupOnly }, enableCrossOsArchive);
             if (!cacheKey) {
+                if (failOnCacheMiss) {
+                    throw new Error(`Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${primaryKey}`);
+                }
                 core.info(`Cache not found for input keys: ${[
                     primaryKey,
                     ...restoreKeys
diff --git a/dist/save-only/index.js b/dist/save-only/index.js
index d849d94..9ac082e 100644
--- a/dist/save-only/index.js
+++ b/dist/save-only/index.js
@@ -5035,6 +5035,7 @@ var Inputs;
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
     Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
+    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
     Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
diff --git a/dist/save/index.js b/dist/save/index.js
index 7005251..5134c6e 100644
--- a/dist/save/index.js
+++ b/dist/save/index.js
@@ -4979,6 +4979,7 @@ var Inputs;
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
     Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
+    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
     Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
diff --git a/package-lock.json b/package-lock.json
index 31d5052..010c342 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "cache",
-  "version": "3.2.3",
+  "version": "3.2.4",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "cache",
-      "version": "3.2.3",
+      "version": "3.2.4",
       "license": "MIT",
       "dependencies": {
         "@actions/cache": "https://github.com/cdce8p/toolkit/raw/cache-dry-run-release/packages/cache/actions-cache-3.1.3.tgz",
diff --git a/package.json b/package.json
index eee9669..6222c78 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "cache",
-  "version": "3.2.3",
+  "version": "3.2.4",
   "private": true,
   "description": "Cache dependencies and build outputs",
   "main": "dist/restore/index.js",
diff --git a/restore/README.md b/restore/README.md
index a6d8b67..6014f8b 100644
--- a/restore/README.md
+++ b/restore/README.md
@@ -7,6 +7,7 @@ The restore action, as the name suggest, restores a cache. It acts similar to th
 * `path` - A list of files, directories, and wildcard patterns to cache and restore. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns.
 * `key` - String used while saving cache for restoring the cache
 * `restore-keys` - An ordered list of prefix-matched keys to use for restoring stale cache if no cache hit occurred for key.
+* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: false
 * `lookup-only` - Skip downloading cache. Only check if cache entry exists. Default: false
 
 ## Outputs
@@ -96,7 +97,7 @@ steps:
 
 ### Exit workflow on cache miss
 
-You can use the output of this action to exit the workflow on cache miss. This way you can restrict your workflow to only initiate the build when `cache-hit` occurs, in other words, cache with exact key is found.
+You can use `fail-on-cache-miss: true` to exit the workflow on a cache miss. This way you can restrict your workflow to only initiate the build when a cache is matched. Also, if you want to fail if cache did not match primary key, additionally leave `restore-keys` empty!
 
 ```yaml
 steps:
@@ -107,10 +108,7 @@ steps:
     with:
       path: path/to/dependencies
       key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
-
-  - name: Check cache hit
-    if: steps.cache.outputs.cache-hit != 'true'
-    run: exit 1
+      fail-on-cache-miss: true
 
   - name: Build
     run: /build.sh
diff --git a/restore/action.yml b/restore/action.yml
index db6f05a..6dbca00 100644
--- a/restore/action.yml
+++ b/restore/action.yml
@@ -15,6 +15,10 @@ inputs:
     description: 'An optional boolean when enabled, allows windows runners to restore caches that were saved on other platforms'
     default: 'false'
     required: false
+  fail-on-cache-miss:
+    description: 'Fail the workflow if cache entry is not found'
+    default: 'false'
+    required: false
   lookup-only:
     description: 'Skip downloading cache. Only check if cache entry exists'
     default: 'false'
diff --git a/src/constants.ts b/src/constants.ts
index f3340f9..0158ae0 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -4,6 +4,7 @@ export enum Inputs {
     RestoreKeys = "restore-keys", // Input for cache, restore action
     UploadChunkSize = "upload-chunk-size", // Input for cache, save action
     EnableCrossOsArchive = "enableCrossOsArchive", // Input for cache, restore, save action
+    FailOnCacheMiss = "fail-on-cache-miss", // Input for cache, restore action
     LookupOnly = "lookup-only" // Input for cache, restore action
 }
 
diff --git a/src/restoreImpl.ts b/src/restoreImpl.ts
index 0675b41..048d9fa 100644
--- a/src/restoreImpl.ts
+++ b/src/restoreImpl.ts
@@ -34,6 +34,7 @@ async function restoreImpl(
         const enableCrossOsArchive = utils.getInputAsBool(
             Inputs.EnableCrossOsArchive
         );
+        const failOnCacheMiss = utils.getInputAsBool(Inputs.FailOnCacheMiss);
         const lookupOnly = utils.getInputAsBool(Inputs.LookupOnly);
 
         const cacheKey = await cache.restoreCache(
@@ -45,6 +46,11 @@ async function restoreImpl(
         );
 
         if (!cacheKey) {
+            if (failOnCacheMiss) {
+                throw new Error(
+                    `Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${primaryKey}`
+                );
+            }
             core.info(
                 `Cache not found for input keys: ${[
                     primaryKey,
diff --git a/src/utils/testUtils.ts b/src/utils/testUtils.ts
index 4479c6e..ba0670b 100644
--- a/src/utils/testUtils.ts
+++ b/src/utils/testUtils.ts
@@ -14,6 +14,7 @@ interface CacheInput {
     key: string;
     restoreKeys?: string[];
     enableCrossOsArchive?: boolean;
+    failOnCacheMiss?: boolean;
     lookupOnly?: boolean;
 }
 
@@ -27,6 +28,8 @@ export function setInputs(input: CacheInput): void {
             Inputs.EnableCrossOsArchive,
             input.enableCrossOsArchive.toString()
         );
+    input.failOnCacheMiss !== undefined &&
+        setInput(Inputs.FailOnCacheMiss, input.failOnCacheMiss.toString());
     input.lookupOnly !== undefined &&
         setInput(Inputs.LookupOnly, input.lookupOnly.toString());
 }
@@ -37,5 +40,6 @@ export function clearInputs(): void {
     delete process.env[getInputName(Inputs.RestoreKeys)];
     delete process.env[getInputName(Inputs.UploadChunkSize)];
     delete process.env[getInputName(Inputs.EnableCrossOsArchive)];
+    delete process.env[getInputName(Inputs.FailOnCacheMiss)];
     delete process.env[getInputName(Inputs.LookupOnly)];
 }
diff --git a/tips-and-workarounds.md b/tips-and-workarounds.md
index 3a63d24..0cf05a4 100644
--- a/tips-and-workarounds.md
+++ b/tips-and-workarounds.md
@@ -22,7 +22,9 @@ Reusing cache across feature branches is not allowed today to provide cache [iso
 ## Cross OS cache
 From `v3.2.3` cache is cross-os compatible when `enableCrossOsArchive` input is passed as true. This means that a cache created on `ubuntu-latest` or `mac-latest` can be used by `windows-latest` and vice versa, provided the workflow which runs on `windows-latest` have input `enableCrossOsArchive` as true. This is useful to cache dependencies which are independent of the runner platform. This will help reduce the consumption of the cache quota and help build for multiple platforms from the same cache. Things to keep in mind while using this feature:
 - Only cache those files which are compatible across OSs.
-- Caching symlinks might cause issues while restoration as they work differently on different OSs. 
+- Caching symlinks might cause issues while restoration as they work differently on different OSs.
+- Only cache files from within your github workspace directory. 
+- Avoid using directory pointers such as `${{ github.workspace }}` or `~` (home) which eventually evaluate to an absolute path and will not match across OSs.
 
 ## Force deletion of caches overriding default cache eviction policy
 Caches have [branch scope restriction](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache) in place. This means that if caches for a specific branch are using a lot of storage quota, it may result into more frequently used caches from `default` branch getting thrashed. For example, if there are many pull requests happening on a repo and are creating caches, these cannot be used in default branch scope but will still occupy a lot of space till they get cleaned up by [eviction policy](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy). But sometime we want to clean them up on a faster cadence so as to ensure default branch is not thrashing. In order to achieve this, [gh-actions-cache cli](https://github.com/actions/gh-actions-cache/) can be used to delete caches for specific branches.
@@ -67,4 +69,4 @@ jobs:
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 ```
-</details>
\ No newline at end of file
+</details>