Library / SDK
eslint-community/eslint-plugin-promise avatar
eslint-community/eslint-plugin-promise

eslint-plugin-promise: linting promise chains for a consistent house style

Enforce best practices for JavaScript promises

1,005 stars105 forksJavaScriptISC

At a glance

What is it?
eslint-plugin-promise is an ESLint plugin with seventeen rules that police how promises are created, returned, chained and handled, from always-return to no-multiple-resolved. It suits teams with a shared JavaScript style that want the promise rules enforced by the linter rather than left to code review.
Who is it for?
eslint-plugin-promise is a good fit for a team that has already settled on a promise style, that uses ESLint in flat or legacy configuration, and that wants the arguments about always returning from a then block settled once in a shared config.
Can I use it commercially?
Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Eighteen rules, and a recommended set of seven

The plugin's value is in the granularity of the rules rather than in any single clever check. The rule list covers seventeen names, and each maps to a specific mistake. always-return requires a return inside each then call so chains stay readable and reusable. catch-or-return enforces a catch on un-returned promises. no-return-wrap stops you wrapping a value in Promise.resolve or Promise.reject when it is not needed. no-multiple-resolved disallows creating new promises with paths that resolve more than once. param-names enforces consistent parameter names and ordering when creating a new promise, and valid-params enforces the correct number of arguments to promise functions. On the other side, avoid-new and no-native are about how promises are constructed rather than how they are consumed, with avoid-new pointing you at util.promisify and no-native requiring a Promise constructor before use in an ES5 environment. Only a handful of rules are in the recommended preset, which tells you the plugin is not trying to impose a house style on everyone who installs it.

Several rules exist to flag code a modern codebase no longer writes

A second group of rules is about shapes that were common in the promise era and are now rare, and this is where a team needs to think before enabling anything. no-native requires creating a Promise constructor before using it in an ES5 environment, which only matters if you still target ES5. no-callback-in-promise disallows calling a callback inside a then block, pointing you at util.callbackify, and no-promise-in-callback is the mirror image, disallowing promises inside callbacks, and neither describes code an async and await codebase will usually contain. no-return-in-finally disallows return statements inside a finally block. spec-only disallows non-standard promise static methods. Then there are the two prefer rules, prefer-await-to-then and prefer-await-to-callbacks, which push the opposite direction, toward async and await, and prefer-catch which prefers catch over a second argument to then. The two prefer-await rules are not in the recommended configuration, so a team that has already standardised on async and await has to opt into them by name, while a team that wants to move that way can use them as the migration lever.

Installing it takes two npm commands

The setup is the ordinary two step for an ESLint plugin, and the documentation is explicit that ESLint itself has to be there first:

sh
npm install eslint --save-dev

Then the plugin itself:

sh
npm install eslint-plugin-promise --save-dev

Both go in as development dependencies, which is the right place for a linter plugin even though some teams end up installing the plugin globally and regret it. The documentation calls out that specific case: if you installed ESLint globally using the -g flag, then you must also install eslint-plugin-promise globally. That note exists because ESLint resolves plugins relative to where ESLint itself is installed, so a global ESLint cannot see a plugin that lives in a project directory. It is a small trap, and it is the kind of thing that costs an afternoon the first time it happens. The npm package is eslint-plugin-promise at version 7.3.0, published as CommonJS with the entry point at index.js and the rule implementations under a rules directory.

Two configuration formats, and the rules are turned on by name

The plugin supports both configuration styles, which is the main reason to look at it now rather than only when you are starting a new project. In a legacy .eslintrc file you add the plugin to the plugins section and may omit the eslint-plugin- prefix:

json
{
  "plugins": ["promise"]
}

Then each rule is configured under rules, using the promise/ prefix:

json
{
  "rules": {
    "promise/always-return": "error",
    "promise/no-return-wrap": "error",
    "promise/param-names": "error",
    "promise/catch-or-return": "error",
    "promise/no-native": "off",
    "promise/no-nesting": "warn"
  }
}

The severity choice is where the plugin becomes useful in practice, because not every rule deserves to break a build. The example in the documentation mixes error and warn, and turns no-native off entirely, which is a reasonable starting point for a team on a modern Node version. In flat config the plugin is imported directly and a preset is referenced by key:

js
import pluginPromise from 'eslint-plugin-promise'
export default [
  // ...
  pluginPromise.configs['flat/recommended'],
]

In the legacy format the same idea is an extends entry:

json
{
  "extends": ["plugin:promise/recommended"]
}

The distinction between the two presets matters when you read the rules table, because a rule marked as set in one configuration may not be set in the other.

Two rules can be fixed automatically, and one of them changes behaviour

The rules table marks which rules are automatically fixable by the ESLint --fix command line option, and only two are: no-new-statics, which disallows calling new on a promise static method, and prefer-catch, which prefers catch over then with a rejection handler. The fix for prefer-catch is a rewrite rather than a formatting change, since it turns a two argument then into a then plus a catch, and the fix for no-new-statics removes the new call. Both are safe to run as a batch fix, and both are worth applying deliberately rather than letting them land in an unrelated commit. The rest of the rules need a human decision, which is expected for rules that touch control flow. The table also distinguishes rules set in the recommended configuration from rules set in the flat/recommended configuration, and lists which rules are enabled, set to warn or disabled, so you can read the intended posture of the plugin before you pick a subset.

The plugin is small, the test coverage requirement is not

The repository layout shows how little code this is. The entry point is index.js, the rules live in a rules directory, the tests are in __tests__, the documentation in a docs directory with a page per rule, and the generated rule table in the README is produced by a tool whose configuration file is .eslint-doc-generatorrc.js. The build is plain CommonJS with no build step, and the scripts in package.json show the workflow: format runs prettier and eslint together, lint runs the lint scripts through npm-run-all, and test runs jest with coverage. The jest configuration sets a coverage threshold of 100 for branches, functions, lines and statements, with coverage collected from the rule files and an explicit exclusion for a compatibility helper. A plugin with this few rules holding itself to full branch coverage is a good sign about the care behind it, and it is also a signal about what contributing looks like here. The lint:eslint-docs script regenerates the documentation and then fails if the git diff is not clean, which means a change to a rule description that forgets to regenerate the table will not pass CI.

ISC licensed, community maintained, three named maintainers

The licence is ISC, which the documentation states for two copyright holders, an earlier author from 2015 and a later one from 2016, and the package metadata agrees, with the licence field set to ISC and the author listed as jden. The project lives under the eslint-community organisation, which is the piece of context that matters most for its future. A plugin for promises that sat in one person's repository would be a risk for a team depending on it, because the rules encode opinions about style that have to be maintained as the language changes, and eslint-community is an umbrella for plugins that outlive their original authors. Three maintainers are named, with their GitHub handles, and the project uses husky for git hooks and prettier for formatting, with the proseWrap setting set to always so the markdown wraps the way the table format expects. The release history shows v7.3.0 on 2026-04-27, after v7.2.1 and v7.2.0 in November 2024, and the last push was on 2026-10-13, so the source is being worked on even though the tagged releases are spaced out.

Editorial conclusion

eslint-plugin-promise is a good fit for a team that has already settled on a promise style, that uses ESLint in flat or legacy configuration, and that wants the arguments about always returning from a then block settled once in a shared config. It is the wrong tool for a codebase still deciding between callbacks, promises and async functions, and it is the wrong tool for a project that has moved to async and await everywhere, since the promise-oriented rules then have little left to inspect. Before enabling it, read the rules table in the documentation, because the recommended set is deliberately narrow and some rules exist to flag code that a modern codebase will no longer contain. The plugin is published under the ISC licence, the latest version is 7.3.0 from 2026-04-27, and the last push was on 2026-10-13.

Frequently asked questions

How do I install eslint-plugin-promise?

Install ESLint first with npm install eslint --save-dev, then install the plugin with npm install eslint-plugin-promise --save-dev. If you installed ESLint globally with the -g flag, the documentation notes you must also install eslint-plugin-promise globally.

How do I enable the plugin in a flat config file?

Import the plugin and reference its recommended preset from the exported config array. The documented form is an import of pluginPromise from 'eslint-plugin-promise' followed by pluginPromise.configs['flat/recommended'] as one entry in the array.

How do I enable the plugin in an .eslintrc file?

Add promise to the plugins section, where the eslint-plugin- prefix may be omitted, and then configure individual rules under the rules section using the promise/ prefix. You can instead extend the preset with "extends": ["plugin:promise/recommended"] to start from the recommended rule set.

Which eslint-plugin-promise rules are automatically fixable?

Two are marked as fixable by the ESLint --fix option: no-new-statics, which disallows calling new on a promise static method, and prefer-catch, which prefers catch over then with a rejection handler. The other rules require a human edit.

What is the latest version of eslint-plugin-promise and what licence does it use?

The latest version is 7.3.0, published on 2026-04-27, and the last push was on 2026-10-13. The plugin is published under the ISC licence, and it is maintained under the eslint-community organisation with three named maintainers.

Official sources

  1. eslint-community/eslint-plugin-promise on GitHub
  2. Issues
  3. License: ISC
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/eslint-community-eslint-plugin-promise.svg)](https://hysenlabs.com/projects/eslint-community-eslint-plugin-promise)

Was this useful?